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