• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getResourceLimit(NegativeTestContext & ctx,GLenum resource)78 int getResourceLimit (NegativeTestContext& ctx, GLenum resource)
79 {
80 	int limit = 0;
81 	ctx.glGetIntegerv(resource, &limit);
82 
83 	return limit;
84 }
85 
verifyLinkError(NegativeTestContext & ctx,const glu::ShaderProgram & program)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 
verifyCompileError(NegativeTestContext & ctx,const glu::ShaderProgram & program,glu::ShaderType shaderType)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 
generateComputeShader(NegativeTestContext & ctx,const string & shaderDeclarations,const string & shaderBody)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 
genBuiltInSource(glu::ShaderType shaderType)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 
exceed_uniform_block_limit(NegativeTestContext & ctx)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 
exceed_shader_storage_block_limit(NegativeTestContext & ctx)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 
exceed_texture_image_units_limit(NegativeTestContext & ctx)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 
exceed_image_uniforms_limit(NegativeTestContext & ctx)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 
exceed_shared_memory_size_limit(NegativeTestContext & ctx)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 
exceed_uniform_components_limit(NegativeTestContext & ctx)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 
exceed_atomic_counter_buffer_limit(NegativeTestContext & ctx)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 
exceed_atomic_counters_limit(NegativeTestContext & ctx)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 
program_not_active(NegativeTestContext & ctx)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 
invalid_program_query(NegativeTestContext & ctx)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 
invalid_dispatch_compute_indirect(NegativeTestContext & ctx)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 
invalid_maximum_work_group_counts(NegativeTestContext & ctx)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 
invalid_maximum_work_group_sizes(NegativeTestContext & ctx)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 
invalid_layout_qualifiers(NegativeTestContext & ctx)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 
invalid_write_built_in_constants(NegativeTestContext & ctx)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 
getNegativeComputeTestFunctions(void)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