Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2017 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 Compute tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fNegativeComputeTests.hpp"
     25 #include "gluContextInfo.hpp"
     26 #include "gluShaderProgram.hpp"
     27 #include "glwDefs.hpp"
     28 #include "glwEnums.hpp"
     29 #include "tcuStringTemplate.hpp"
     30 
     31 namespace deqp
     32 {
     33 
     34 using std::string;
     35 using std::map;
     36 
     37 namespace gles31
     38 {
     39 namespace Functional
     40 {
     41 namespace NegativeTestShared
     42 {
     43 namespace
     44 {
     45 
     46 using tcu::TestLog;
     47 using namespace glw;
     48 
     49 static const char* const vertexShaderSource			=	"${GLSL_VERSION_STRING}\n"
     50 														"\n"
     51 														"void main (void)\n"
     52 														"{\n"
     53 														"	gl_Position = vec4(0.0);\n"
     54 														"}\n";
     55 
     56 static const char* const fragmentShaderSource		=	"${GLSL_VERSION_STRING}\n"
     57 														"precision mediump float;\n"
     58 														"layout(location = 0) out mediump vec4 fragColor;\n"
     59 														"\n"
     60 														"void main (void)\n"
     61 														"{\n"
     62 														"	fragColor = vec4(1.0);\n"
     63 														"}\n";
     64 
     65 static const char* const computeShaderSource		=	"${GLSL_VERSION_STRING}\n"
     66 														"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
     67 														"void main (void)\n"
     68 														"{\n"
     69 														"}\n";
     70 
     71 static const char* const invalidComputeShaderSource	=	"${GLSL_VERSION_STRING}\n"
     72 														"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
     73 														"void main (void)\n"
     74 														"{\n"
     75 														"	highp uint var = -1;\n" // error
     76 														"}\n";
     77 
     78 int getResourceLimit (NegativeTestContext& ctx, GLenum resource)
     79 {
     80 	int limit = 0;
     81 	ctx.glGetIntegerv(resource, &limit);
     82 
     83 	return limit;
     84 }
     85 
     86 void verifyLinkError (NegativeTestContext& ctx, const glu::ShaderProgram& program)
     87 {
     88 	bool testFailed = false;
     89 
     90 	tcu::TestLog& log = ctx.getLog();
     91 	log << program;
     92 
     93 	testFailed = program.getProgramInfo().linkOk;
     94 
     95 	if (testFailed)
     96 	{
     97 		const char* const message("Program was not expected to link.");
     98 		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
     99 		ctx.fail(message);
    100 	}
    101 }
    102 
    103 void verifyCompileError (NegativeTestContext& ctx, const glu::ShaderProgram& program, glu::ShaderType shaderType)
    104 {
    105 	bool testFailed = false;
    106 
    107 	tcu::TestLog& log = ctx.getLog();
    108 	log << program;
    109 
    110 	testFailed = program.getShaderInfo(shaderType).compileOk;
    111 
    112 	if (testFailed)
    113 	{
    114 		const char* const message("Program was not expected to compile.");
    115 		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
    116 		ctx.fail(message);
    117 	}
    118 }
    119 
    120 string generateComputeShader (NegativeTestContext& ctx, const string& shaderDeclarations, const string& shaderBody)
    121 {
    122 	const bool			isES32			= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    123 	const char* const	shaderVersion	= isES32
    124 										? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES)
    125 										: getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    126 
    127 	std::ostringstream compShaderSource;
    128 
    129 	compShaderSource	<<	shaderVersion << "\n"
    130 						<<	"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
    131 						<<	shaderDeclarations << "\n"
    132 						<<	"void main (void)\n"
    133 						<<	"{\n"
    134 						<<	shaderBody
    135 						<<	"}\n";
    136 
    137 	return compShaderSource.str();
    138 }
    139 
    140 string genBuiltInSource (glu::ShaderType shaderType)
    141 {
    142 	std::ostringstream		source;
    143 	source << "${GLSL_VERSION_STRING}\n";
    144 
    145 	switch (shaderType)
    146 	{
    147 		case glu::SHADERTYPE_VERTEX:
    148 		case glu::SHADERTYPE_FRAGMENT:
    149 			break;
    150 
    151 		case glu::SHADERTYPE_COMPUTE:
    152 			source << "layout (local_size_x = 1) in;\n";
    153 			break;
    154 
    155 		case glu::SHADERTYPE_GEOMETRY:
    156 			source << "layout(points) in;\n"
    157 				   << "layout(line_strip, max_vertices = 3) out;\n";
    158 			break;
    159 
    160 		case glu::SHADERTYPE_TESSELLATION_CONTROL:
    161 			source << "${GLSL_TESS_EXTENSION_STRING}\n"
    162 				   << "layout(vertices = 10) out;\n";
    163 			break;
    164 
    165 		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
    166 			source << "${GLSL_TESS_EXTENSION_STRING}\n"
    167 				   << "layout(triangles) in;\n";
    168 			break;
    169 
    170 		default:
    171 			DE_FATAL("Unknown shader type");
    172 			break;
    173 	}
    174 
    175 	source	<< "\n"
    176 			<< "void main(void)\n"
    177 			<< "{\n"
    178 			<< "${COMPUTE_BUILT_IN_CONSTANTS_STRING}"
    179 			<< "}\n";
    180 
    181 	return source.str();
    182 }
    183 
    184 void exceed_uniform_block_limit (NegativeTestContext& ctx)
    185 {
    186 	std::ostringstream shaderDecl;
    187 	std::ostringstream shaderBody;
    188 
    189 	shaderDecl	<< "layout(std140, binding = 0) uniform Block\n"
    190 				<< "{\n"
    191 				<< "    highp vec4 val;\n"
    192 				<< "} block[" << getResourceLimit(ctx, GL_MAX_COMPUTE_UNIFORM_BLOCKS) + 1 << "];\n";
    193 
    194 	glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources()
    195 			<< glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
    196 
    197 	ctx.beginSection("Link error is generated if a compute shader exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS.");
    198 	verifyLinkError(ctx, program);
    199 	ctx.endSection();
    200 }
    201 
    202 void exceed_shader_storage_block_limit (NegativeTestContext& ctx)
    203 {
    204 	std::ostringstream shaderDecl;
    205 	std::ostringstream shaderBody;
    206 
    207 	shaderDecl	<< "layout(std140, binding = 0) buffer Block\n"
    208 				<< "{\n"
    209 				<< "    highp vec4 val;\n"
    210 				<< "} block[" << getResourceLimit(ctx, GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS) + 1 << "];\n";
    211 
    212 	glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources()
    213 			<< glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
    214 
    215 	ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS.");
    216 	verifyLinkError(ctx, program);
    217 	ctx.endSection();
    218 }
    219 
    220 void exceed_texture_image_units_limit (NegativeTestContext& ctx)
    221 {
    222 	const int			limit			= getResourceLimit(ctx, GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS) + 1;
    223 	std::ostringstream	shaderDecl;
    224 	std::ostringstream	shaderBody;
    225 
    226 	shaderDecl	<< "layout(binding = 0) "
    227 				<< "uniform highp sampler2D u_sampler[" << limit + 1 << "];\n"
    228 				<< "\n"
    229 				<< "layout(binding = 0) buffer Output {\n"
    230 				<< "    vec4 values[ " << limit + 1 << " ];\n"
    231 				<< "} sb_out;\n";
    232 
    233 	for (int i = 0; i < limit + 1; ++i)
    234 		shaderBody	<< "   sb_out.values[" << i << "] = texture(u_sampler[" << i << "], vec2(1.0f));\n";
    235 
    236 	glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources()
    237 			<< glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
    238 
    239 	tcu::TestLog& log = ctx.getLog();
    240 	log << tcu::TestLog::Message << "Possible link error is generated if compute shader exceeds GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS." << tcu::TestLog::EndMessage;
    241 	log << program;
    242 
    243 	if (program.getProgramInfo().linkOk)
    244 	{
    245 		log << tcu::TestLog::Message << "Quality Warning: program was not expected to link." << tcu::TestLog::EndMessage;
    246 		ctx.glUseProgram(program.getProgram());
    247 		ctx.expectError(GL_NO_ERROR);
    248 
    249 		ctx.beginSection("GL_INVALID_OPERATION error is generated if the sum of the number of active samplers for each active program exceeds the maximum number of texture image units allowed");
    250 		ctx.glDispatchCompute(1, 1, 1);
    251 		ctx.expectError(GL_INVALID_OPERATION);
    252 		ctx.endSection();
    253 	}
    254 }
    255 
    256 void exceed_image_uniforms_limit (NegativeTestContext& ctx)
    257 {
    258 	const int			limit = getResourceLimit(ctx, GL_MAX_COMPUTE_IMAGE_UNIFORMS);
    259 	std::ostringstream	shaderDecl;
    260 	std::ostringstream	shaderBody;
    261 
    262 	shaderDecl	<< "layout(rgba8, binding = 0) "
    263 				<< "uniform readonly highp image2D u_image[" << limit + 1 << "];\n"
    264 				<< "\n"
    265 				<< "layout(binding = 0) buffer Output {\n"
    266 				<< "    float values[" << limit + 1 << "];\n"
    267 				<< "} sb_out;\n";
    268 
    269 	for (int i = 0; i < limit + 1; ++i)
    270 		shaderBody	<< "    sb_out.values[" << i << "]" << "  = imageLoad(u_image[" << i << "], ivec2(gl_GlobalInvocationID.xy)).x;\n";
    271 
    272 	glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources()
    273 			<< glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
    274 
    275 	ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_IMAGE_UNIFORMS.");
    276 	verifyLinkError(ctx, program);
    277 	ctx.endSection();
    278 }
    279 
    280 void exceed_shared_memory_size_limit (NegativeTestContext& ctx)
    281 {
    282 	const int			limit				= getResourceLimit(ctx, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
    283 	const long			numberOfElements	= limit / sizeof(GLuint);
    284 	std::ostringstream	shaderDecl;
    285 	std::ostringstream	shaderBody;
    286 
    287 	shaderDecl	<< "shared uint values[" << numberOfElements + 1 << "];\n"
    288 				<< "\n"
    289 				<< "layout(binding = 0) buffer Output {\n"
    290 				<< "    uint values;\n"
    291 				<< "} sb_out;\n";
    292 
    293 	shaderBody	<< "    sb_out.values = values[" << numberOfElements << "];\n";
    294 
    295 	glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources()
    296 			<< glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
    297 
    298 	ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_SHARED_MEMORY_SIZE.");
    299 	verifyLinkError(ctx, program);
    300 	ctx.endSection();
    301 }
    302 
    303 void exceed_uniform_components_limit (NegativeTestContext& ctx)
    304 {
    305 	const int			limit = getResourceLimit(ctx, GL_MAX_COMPUTE_UNIFORM_COMPONENTS);
    306 	std::ostringstream	shaderDecl;
    307 	std::ostringstream	shaderBody;
    308 
    309 	shaderDecl	<< "uniform highp uint u_value[" << limit + 1 << "];\n"
    310 				<< "\n"
    311 				<< "layout(binding = 0) buffer Output {\n"
    312 				<< "    uint values[2];\n"
    313 				<< "} sb_out;\n";
    314 
    315 	shaderBody << "    sb_out.values[0] = u_value[" << limit << "];\n";
    316 	shaderBody << "    sb_out.values[1] = u_value[0];\n";
    317 
    318 	glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources()
    319 			<< glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
    320 
    321 	ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_UNIFORM_COMPONENTS.");
    322 	verifyLinkError(ctx, program);
    323 	ctx.endSection();
    324 }
    325 
    326 void exceed_atomic_counter_buffer_limit (NegativeTestContext& ctx)
    327 {
    328 	const int			limit = getResourceLimit(ctx, GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS);
    329 	std::ostringstream	shaderDecl;
    330 	std::ostringstream	shaderBody;
    331 
    332 	for (int i = 0; i < limit + 1; ++i)
    333 	{
    334 		shaderDecl	<< "layout(binding = " << i << ") "
    335 					<< "uniform atomic_uint u_atomic" << i << ";\n";
    336 
    337 		if (i == 0)
    338 			shaderBody	<< "    uint oldVal = atomicCounterIncrement(u_atomic" << i << ");\n";
    339 		else
    340 			shaderBody	<< "    oldVal = atomicCounterIncrement(u_atomic" << i << ");\n";
    341 	}
    342 
    343 	shaderBody	<< "    sb_out.value = oldVal;\n";
    344 
    345 	shaderDecl	<< "\n"
    346 				<< "layout(binding = 0) buffer Output {\n"
    347 				<< "    uint value;\n"
    348 				<< "} sb_out;\n";
    349 
    350 	glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources()
    351 			<< glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
    352 
    353 	ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS.");
    354 	verifyLinkError(ctx, program);
    355 	ctx.endSection();
    356 }
    357 
    358 void exceed_atomic_counters_limit (NegativeTestContext& ctx)
    359 {
    360 	std::ostringstream	shaderDecl;
    361 	std::ostringstream	shaderBody;
    362 
    363 	shaderDecl	<< "layout(binding = 0, offset = 0) uniform atomic_uint u_atomic0;\n"
    364 				<< "layout(binding = " << sizeof(GLuint) * getResourceLimit(ctx, GL_MAX_COMPUTE_ATOMIC_COUNTERS) << ", offset = 0) uniform atomic_uint u_atomic1;\n"
    365 				<< "\n"
    366 				<< "layout(binding = 0) buffer Output {\n"
    367 				<< "    uint value;\n"
    368 				<< "} sb_out;\n";
    369 
    370 	shaderBody	<< "    uint oldVal = 0u;\n"
    371 				<< "    oldVal = atomicCounterIncrement(u_atomic0);\n"
    372 				<< "    oldVal = atomicCounterIncrement(u_atomic1);\n"
    373 				<< "    sb_out.value = oldVal;\n";
    374 
    375 	glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources()
    376 			<< glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
    377 
    378 	ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTERS.");
    379 	verifyLinkError(ctx, program);
    380 	ctx.endSection();
    381 }
    382 
    383 void program_not_active (NegativeTestContext& ctx)
    384 {
    385 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    386 	map<string, string>			args;
    387 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    388 
    389 	const glu::VertexSource		vertSource(tcu::StringTemplate(vertexShaderSource).specialize(args));
    390 	const glu::FragmentSource	fragSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
    391 
    392 	glu::ProgramPipeline		pipeline(ctx.getRenderContext());
    393 
    394 	glu::ShaderProgram			vertProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << vertSource);
    395 	glu::ShaderProgram			fragProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << fragSource);
    396 
    397 	tcu::TestLog& log			= ctx.getLog();
    398 	log << vertProgram << fragProgram;
    399 
    400 	if (!vertProgram.isOk() || !fragProgram.isOk())
    401 		TCU_THROW(InternalError, "failed to build program");
    402 
    403 	ctx.glBindProgramPipeline(pipeline.getPipeline());
    404 	ctx.expectError(GL_NO_ERROR);
    405 
    406 	ctx.beginSection("Program not set at all");
    407 	{
    408 		ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchCompute if there is no active program for the compute shader stage.");
    409 		ctx.glDispatchCompute(1, 1, 1);
    410 		ctx.expectError(GL_INVALID_OPERATION);
    411 		ctx.endSection();
    412 
    413 		ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if there is no active program for the compute shader stage.");
    414 		GLintptr indirect = 0;
    415 		ctx.glDispatchComputeIndirect(indirect);
    416 		ctx.expectError(GL_INVALID_OPERATION);
    417 		ctx.endSection();
    418 	}
    419 	ctx.endSection();
    420 
    421 	ctx.beginSection("Program contains graphic pipeline stages");
    422 	{
    423 		ctx.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vertProgram.getProgram());
    424 		ctx.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, fragProgram.getProgram());
    425 		ctx.expectError(GL_NO_ERROR);
    426 
    427 		ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchCompute if there is no active program for the compute shader stage.");
    428 		ctx.glDispatchCompute(1, 1, 1);
    429 		ctx.expectError(GL_INVALID_OPERATION);
    430 		ctx.endSection();
    431 
    432 		ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if there is no active program for the compute shader stage.");
    433 		GLintptr indirect = 0;
    434 		ctx.glDispatchComputeIndirect(indirect);
    435 		ctx.expectError(GL_INVALID_OPERATION);
    436 		ctx.endSection();
    437 	}
    438 	ctx.endSection();
    439 
    440 	ctx.glBindProgramPipeline(0);
    441 	ctx.expectError(GL_NO_ERROR);
    442 }
    443 
    444 void invalid_program_query (NegativeTestContext& ctx)
    445 {
    446 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    447 	map<string, string>			args;
    448 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    449 
    450 	GLint data[3] = { 0, 0, 0 };
    451 
    452 	ctx.beginSection("Compute shader that does not link");
    453 	{
    454 		const glu::ComputeSource	compSource(tcu::StringTemplate(invalidComputeShaderSource).specialize(args));
    455 		glu::ShaderProgram			invalidComputeProgram (ctx.getRenderContext(), glu::ProgramSources() << compSource);
    456 
    457 		tcu::TestLog& log = ctx.getLog();
    458 		log << invalidComputeProgram;
    459 
    460 		if (invalidComputeProgram.isOk())
    461 			TCU_THROW(InternalError, "program should not of built");
    462 
    463 		ctx.beginSection("GL_INVALID_OPERATION is generated if GL_COMPUTE_WORK_GROUP_SIZE is queried for a program which has not been linked properly.");
    464 		ctx.glGetProgramiv(invalidComputeProgram.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, &data[0]);
    465 		ctx.expectError(GL_INVALID_OPERATION);
    466 		ctx.endSection();
    467 
    468 		ctx.glUseProgram(0);
    469 	}
    470 	ctx.endSection();
    471 
    472 	ctx.beginSection("Compute shader not present");
    473 	{
    474 		const glu::VertexSource		vertSource(tcu::StringTemplate(vertexShaderSource).specialize(args));
    475 		const glu::FragmentSource	fragSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
    476 		glu::ShaderProgram			graphicsPipelineProgram	(ctx.getRenderContext(), glu::ProgramSources() << vertSource << fragSource);
    477 
    478 		tcu::TestLog& log = ctx.getLog();
    479 		log << graphicsPipelineProgram;
    480 
    481 		if (!graphicsPipelineProgram.isOk())
    482 			TCU_THROW(InternalError, "failed to build program");
    483 
    484 		ctx.beginSection("GL_INVALID_OPERATION is generated if GL_COMPUTE_WORK_GROUP_SIZE is queried for a program which has not been linked properly.");
    485 		ctx.glGetProgramiv(graphicsPipelineProgram.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, &data[0]);
    486 		ctx.expectError(GL_INVALID_OPERATION);
    487 		ctx.endSection();
    488 
    489 		ctx.glUseProgram(0);
    490 	}
    491 	ctx.endSection();
    492 }
    493 
    494 void invalid_dispatch_compute_indirect (NegativeTestContext& ctx)
    495 {
    496 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    497 	map<string, string>			args;
    498 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    499 
    500 	const glu::ComputeSource	compSource(tcu::StringTemplate(computeShaderSource).specialize(args));
    501 	glu::ShaderProgram			program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
    502 
    503 	tcu::TestLog& log = ctx.getLog();
    504 	log << program;
    505 
    506 	if (!program.isOk())
    507 		TCU_THROW(InternalError, "failed to build program");
    508 
    509 	ctx.glUseProgram(program.getProgram());
    510 	ctx.expectError(GL_NO_ERROR);
    511 
    512 	static const struct
    513 	{
    514 		GLuint numGroupsX;
    515 		GLuint numGroupsY;
    516 		GLuint numGroupsZ;
    517 	} data = {0, 0, 0};
    518 
    519 	{
    520 		GLuint buffer;
    521 		ctx.glGenBuffers(1, &buffer);
    522 		ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
    523 		ctx.expectError(GL_NO_ERROR);
    524 
    525 		ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if zero is bound to GL_DISPATCH_INDIRECT_BUFFER.");
    526 		GLintptr indirect = 0;
    527 		ctx.glDispatchComputeIndirect(indirect);
    528 		ctx.expectError(GL_INVALID_OPERATION);
    529 		ctx.endSection();
    530 
    531 		ctx.glDeleteBuffers(1, &buffer);
    532 	}
    533 
    534 	{
    535 		GLuint buffer;
    536 		ctx.glGenBuffers(1, &buffer);
    537 		ctx.expectError(GL_NO_ERROR);
    538 
    539 		ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
    540 		ctx.expectError(GL_NO_ERROR);
    541 
    542 		ctx.glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(data), &data, GL_STATIC_DRAW);
    543 		ctx.expectError(GL_NO_ERROR);
    544 
    545 		ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if data is sourced beyond the end of the buffer object.");
    546 		GLintptr indirect = 1 << 10;
    547 		ctx.glDispatchComputeIndirect(indirect);
    548 		ctx.expectError(GL_INVALID_OPERATION);
    549 		ctx.endSection();
    550 
    551 		ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
    552 		ctx.glDeleteBuffers(1, &buffer);
    553 	}
    554 
    555 	{
    556 		ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchComputeIndirect if the value of indirect is less than zero.");
    557 		GLintptr indirect = -1;
    558 		ctx.glDispatchComputeIndirect(indirect);
    559 		ctx.expectError(GL_INVALID_VALUE);
    560 		ctx.endSection();
    561 	}
    562 
    563 	{
    564 		GLuint buffer;
    565 		ctx.glGenBuffers(1, &buffer);
    566 		ctx.expectError(GL_NO_ERROR);
    567 
    568 		ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
    569 		ctx.expectError(GL_NO_ERROR);
    570 
    571 		ctx.glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(data), &data, GL_STATIC_DRAW);
    572 		ctx.expectError(GL_NO_ERROR);
    573 
    574 		ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchComputeIndirect if indirect is not a multiple of the size, in basic machine units, of uint.");
    575 		GLintptr indirect = sizeof(data) + 1;
    576 		ctx.glDispatchComputeIndirect(indirect);
    577 		ctx.expectError(GL_INVALID_VALUE);
    578 		ctx.endSection();
    579 
    580 		ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
    581 		ctx.glDeleteBuffers(1, &buffer);
    582 	}
    583 }
    584 
    585 void invalid_maximum_work_group_counts (NegativeTestContext& ctx)
    586 {
    587 	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    588 	map<string, string>			args;
    589 	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    590 
    591 	const glu::ComputeSource	compSource(tcu::StringTemplate(computeShaderSource).specialize(args));
    592 	glu::ShaderProgram			program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
    593 
    594 	tcu::TestLog& log = ctx.getLog();
    595 	log << program;
    596 
    597 	if (!program.isOk())
    598 		TCU_THROW(InternalError, "failed to build program");
    599 
    600 	ctx.glUseProgram(program.getProgram());
    601 	ctx.expectError(GL_NO_ERROR);
    602 
    603 	GLint workGroupCountX;
    604 	ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)0, &workGroupCountX);
    605 	ctx.expectError(GL_NO_ERROR);
    606 
    607 	ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsX> array is larger than the maximum work group count for the x dimension.");
    608 	ctx.glDispatchCompute(workGroupCountX+1, 1, 1);
    609 	ctx.expectError(GL_INVALID_VALUE);
    610 	ctx.endSection();
    611 
    612 	GLint workGroupCountY;
    613 	ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)1, &workGroupCountY);
    614 	ctx.expectError(GL_NO_ERROR);
    615 
    616 	ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsY> array is larger than the maximum work group count for the y dimension.");
    617 	ctx.glDispatchCompute(1, workGroupCountY+1, 1);
    618 	ctx.expectError(GL_INVALID_VALUE);
    619 	ctx.endSection();
    620 
    621 	GLint workGroupCountZ;
    622 	ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)2, &workGroupCountZ);
    623 	ctx.expectError(GL_NO_ERROR);
    624 
    625 	ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsZ> array is larger than the maximum work group count for the z dimension.");
    626 	ctx.glDispatchCompute(1, 1, workGroupCountZ+1);
    627 	ctx.expectError(GL_INVALID_VALUE);
    628 	ctx.endSection();
    629 }
    630 
    631 void invalid_maximum_work_group_sizes (NegativeTestContext& ctx)
    632 {
    633 	GLint maxWorkGroupSizeX;
    634 	ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)0, &maxWorkGroupSizeX);
    635 	ctx.expectError(GL_NO_ERROR);
    636 
    637 	GLint maxWorkGroupSizeY;
    638 	ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)1, &maxWorkGroupSizeY);
    639 	ctx.expectError(GL_NO_ERROR);
    640 
    641 	GLint maxWorkGroupSizeZ;
    642 	ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)2, &maxWorkGroupSizeZ);
    643 	ctx.expectError(GL_NO_ERROR);
    644 
    645 	GLint maxWorkGroupInvocations;
    646 	ctx.glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &maxWorkGroupInvocations);
    647 	ctx.expectError(GL_NO_ERROR);
    648 
    649 	DE_ASSERT((maxWorkGroupSizeX * maxWorkGroupSizeY * maxWorkGroupSizeZ) > maxWorkGroupInvocations );
    650 
    651 	const bool				isES32			= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    652 	const char* const		shaderVersion	= isES32
    653 											? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES)
    654 											: getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    655 
    656 	static const struct
    657 	{
    658 		GLint x;
    659 		GLint y;
    660 		GLint z;
    661 	} localWorkGroupSizeCases[] =
    662 	{
    663 		{	maxWorkGroupSizeX+1,	1,						1						},
    664 		{	1,						maxWorkGroupSizeY+1,	1						},
    665 		{	1,						1,						maxWorkGroupSizeZ+1		},
    666 		{	maxWorkGroupSizeX,		maxWorkGroupSizeY,		maxWorkGroupSizeZ		},
    667 	};
    668 
    669 	for (int testCase = 0; testCase < DE_LENGTH_OF_ARRAY(localWorkGroupSizeCases); ++testCase)
    670 	{
    671 		std::ostringstream compShaderSource;
    672 
    673 		compShaderSource	<<	shaderVersion << "\n"
    674 							<<	"layout(local_size_x = " << localWorkGroupSizeCases[testCase].x << ", local_size_y = " << localWorkGroupSizeCases[testCase].y << ", local_size_z = " << localWorkGroupSizeCases[testCase].z << ") in;\n"
    675 							<<	"void main (void)\n"
    676 							<<	"{\n"
    677 							<<	"}\n";
    678 
    679 		const glu::ComputeSource	compSource(compShaderSource.str());
    680 		glu::ShaderProgram			program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
    681 
    682 		if (testCase == DE_LENGTH_OF_ARRAY(localWorkGroupSizeCases)-1)
    683 		{
    684 			bool testFailed = false;
    685 			ctx.beginSection("A compile time or link error is generated if the maximum number of invocations in a single local work group (product of the three dimensions) is greater than GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS.");
    686 
    687 			ctx.getLog() << program;
    688 			testFailed = (program.getProgramInfo().linkOk) && (program.getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk);
    689 
    690 			if (testFailed)
    691 			{
    692 				const char* const message("Program was not expected to compile or link.");
    693 				ctx.getLog() << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
    694 				ctx.fail(message);
    695 			}
    696 		}
    697 		else
    698 		{
    699 			ctx.beginSection("A compile time error is generated if the fixed local group size of the shader in any dimension is greater than the maximum supported.");
    700 			verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE);
    701 		}
    702 
    703 		ctx.endSection();
    704 	}
    705 }
    706 
    707 void invalid_layout_qualifiers (NegativeTestContext& ctx)
    708 {
    709 	const bool				isES32			= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    710 	const char* const		shaderVersion	= isES32
    711 											? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES)
    712 											: getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    713 
    714 	{
    715 		std::ostringstream compShaderSource;
    716 		compShaderSource	<<	shaderVersion << "\n"
    717 							<<	"void main (void)\n"
    718 							<<	"{\n"
    719 							<<	"}\n";
    720 
    721 		const glu::ComputeSource	compSource(compShaderSource.str());
    722 		glu::ShaderProgram			program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
    723 
    724 		ctx.beginSection("A link error is generated if the compute shader program does not contain an input layout qualifier specifying a fixed local group size.");
    725 		verifyLinkError(ctx, program);
    726 		ctx.endSection();
    727 	}
    728 
    729 	{
    730 		std::ostringstream compShaderSource;
    731 		compShaderSource	<<	shaderVersion << "\n"
    732 							<<	"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
    733 							<<	"layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
    734 							<<	"void main (void)\n"
    735 							<<	"{\n"
    736 							<<	"}\n";
    737 
    738 		const glu::ComputeSource	compSource(compShaderSource.str());
    739 		glu::ShaderProgram			program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
    740 
    741 		ctx.beginSection("A compile-time error is generated if a local work group size qualifier is declared more than once in the same shader.");
    742 		verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE);
    743 		ctx.endSection();
    744 	}
    745 
    746 	{
    747 		std::ostringstream compShaderSource;
    748 		compShaderSource	<<	shaderVersion << "\n"
    749 							<<	"out mediump vec4 fragColor;\n"
    750 							<<	"\n"
    751 							<<	"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
    752 							<<	"void main (void)\n"
    753 							<<	"{\n"
    754 							<<	"}\n";
    755 
    756 		const glu::ComputeSource	compSource(compShaderSource.str());
    757 		glu::ShaderProgram			program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
    758 
    759 		ctx.beginSection("A compile-time error is generated if a user defined output variable is declared in a compute shader.");
    760 		verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE);
    761 		ctx.endSection();
    762 	}
    763 
    764 	{
    765 		std::ostringstream compShaderSource;
    766 		compShaderSource	<<	shaderVersion << "\n"
    767 							<<	"uvec3 gl_NumWorkGroups;\n"
    768 							<<	"uvec3 gl_WorkGroupSize;\n"
    769 							<<	"uvec3 gl_WorkGroupID;\n"
    770 							<<	"uvec3 gl_LocalInvocationID;\n"
    771 							<<	"uvec3 gl_GlobalInvocationID;\n"
    772 							<<	"uvec3 gl_LocalInvocationIndex;\n"
    773 							<<	"\n"
    774 							<<	"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
    775 							<<	"void main (void)\n"
    776 							<<	"{\n"
    777 							<<	"}\n";
    778 
    779 		const glu::ComputeSource	compSource(compShaderSource.str());
    780 		glu::ShaderProgram			program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
    781 
    782 		ctx.beginSection("A compile time or link error is generated if compute shader built-in variables are redeclared.");
    783 		bool testFailed = false;
    784 
    785 		tcu::TestLog& log = ctx.getLog();
    786 		log << program;
    787 
    788 		testFailed = (program.getProgramInfo().linkOk) && (program.getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk);
    789 
    790 		if (testFailed)
    791 		{
    792 			const char* const message("Program was not expected to compile or link.");
    793 			log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
    794 			ctx.fail(message);
    795 		}
    796 
    797 		ctx.endSection();
    798 	}
    799 }
    800 
    801 void invalid_write_built_in_constants (NegativeTestContext& ctx)
    802 {
    803 	if ((!ctx.isExtensionSupported("GL_EXT_tessellation_shader") && !ctx.isExtensionSupported("GL_OES_tessellation_shader")) ||
    804 	    (!ctx.isExtensionSupported("GL_EXT_geometry_shader") && !ctx.isExtensionSupported("GL_OES_geometry_shader")))
    805 	{
    806 		TCU_THROW(NotSupportedError, "tessellation and geometry shader extensions not supported");
    807 	}
    808 
    809 	const bool					isES32			= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    810 	map<string, string>			args;
    811 
    812 	args["GLSL_VERSION_STRING"]					=	isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    813 	args["GLSL_TESS_EXTENSION_STRING"]			=	isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
    814 	args["COMPUTE_BUILT_IN_CONSTANTS_STRING"]	=	"	gl_MaxComputeWorkGroupCount       = ivec3(65535, 65535, 65535);\n"
    815 													"	gl_MaxComputeWorkGroupCount       = ivec3(1024, 1024, 64);\n"
    816 													"	gl_MaxComputeWorkGroupSize        = ivec3(512);\n"
    817 													"	gl_MaxComputeUniformComponents    = 512;\n"
    818 													"	gl_MaxComputeTextureImageUnits    = 16;\n"
    819 													"	gl_MaxComputeImageUniforms        = 8;\n"
    820 													"	gl_MaxComputeAtomicCounters       = 8;\n"
    821 													"	gl_MaxComputeAtomicCounterBuffers = 1;\n";
    822 
    823 	const glu::VertexSource					vertSource		(tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_VERTEX)).specialize(args));
    824 	const glu::FragmentSource				fragSource		(tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_FRAGMENT)).specialize(args));
    825 	const glu::TessellationControlSource	tessCtrlSource	(tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_TESSELLATION_CONTROL)).specialize(args));
    826 	const glu::TessellationEvaluationSource	tessEvalSource	(tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_TESSELLATION_EVALUATION)).specialize(args));
    827 	const glu::GeometrySource				geometrySource	(tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_GEOMETRY)).specialize(args));
    828 	const glu::ComputeSource				computeSource	(tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_COMPUTE)).specialize(args));
    829 
    830 	glu::ShaderProgram	vertProgram		(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << vertSource);
    831 	glu::ShaderProgram	fragProgram		(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << fragSource);
    832 	glu::ShaderProgram	tessCtrlProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource);
    833 	glu::ShaderProgram	tessEvalProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource);
    834 	glu::ShaderProgram	geometryProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << geometrySource);
    835 	glu::ShaderProgram	computeProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << computeSource);
    836 
    837 	ctx.beginSection("A compile time is generated if compute built-in constants provided in all shaders are written to.");
    838 	verifyCompileError(ctx, vertProgram, glu::SHADERTYPE_VERTEX);
    839 	verifyCompileError(ctx, fragProgram, glu::SHADERTYPE_FRAGMENT);
    840 	verifyCompileError(ctx, tessCtrlProgram, glu::SHADERTYPE_TESSELLATION_CONTROL);
    841 	verifyCompileError(ctx, tessEvalProgram, glu::SHADERTYPE_TESSELLATION_EVALUATION);
    842 	verifyCompileError(ctx, geometryProgram, glu::SHADERTYPE_GEOMETRY);
    843 	verifyCompileError(ctx, computeProgram, glu::SHADERTYPE_COMPUTE);
    844 	ctx.endSection();
    845 }
    846 
    847 } // anonymous
    848 
    849 std::vector<FunctionContainer> getNegativeComputeTestFunctions (void)
    850 {
    851 	const FunctionContainer funcs[] =
    852 	{
    853 		{ program_not_active,					"program_not_active",					"Use dispatch commands with no active program"									},
    854 		{ invalid_program_query,				"invalid_program_query",				"Querying GL_COMPUTE_WORK_GROUP_SIZE with glGetProgramiv() on invalid programs"	},
    855 		{ invalid_dispatch_compute_indirect,	"invalid_dispatch_compute_indirect",	"Invalid glDispatchComputeIndirect usage"										},
    856 		{ invalid_maximum_work_group_counts,	"invalid_maximum_work_group_counts",	"Maximum workgroup counts for dispatch commands"								},
    857 		{ invalid_maximum_work_group_sizes,		"invalid_maximum_work_group_sizes",		"Maximum local workgroup sizes declared in compute shaders"						},
    858 		{ invalid_layout_qualifiers,			"invalid_layout_qualifiers",			"Invalid layout qualifiers in compute shaders"									},
    859 		{ invalid_write_built_in_constants,		"invalid_write_built_in_constants",		"Invalid writes to built-in compute shader constants"							},
    860 		{ exceed_uniform_block_limit,			"exceed_uniform_block_limit",			"Link error when shader exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS"					},
    861 		{ exceed_shader_storage_block_limit,	"exceed_shader_storage_block_limit",	"Link error when shader exceeds GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"			},
    862 		{ exceed_texture_image_units_limit,		"exceed_texture_image_units_limit",		"Link error when shader exceeds GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"				},
    863 		{ exceed_image_uniforms_limit,			"exceed_image_uniforms_limit",			"Link error when shader exceeds GL_MAX_COMPUTE_IMAGE_UNIFORMS"					},
    864 		{ exceed_shared_memory_size_limit,		"exceed_shared_memory_size_limit",		"Link error when shader exceeds GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"				},
    865 		{ exceed_uniform_components_limit,		"exceed_uniform_components_limit",		"Link error when shader exceeds GL_MAX_COMPUTE_UNIFORM_COMPONENTS"				},
    866 		{ exceed_atomic_counter_buffer_limit,	"exceed_atomic_counter_buffer_limit",	"Link error when shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"			},
    867 		{ exceed_atomic_counters_limit,			"exceed_atomic_counters_limit",			"Link error when shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTERS"					},
    868 	};
    869 
    870 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    871 }
    872 
    873 } // NegativeTestShared
    874 } // Functional
    875 } // gles31
    876 } // deqp
    877