Add new compute negative coverage tests
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fNegativeComputeTests.cpp
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_VALUE);
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 = 0, offset = " << sizeof(GLuint) * getResourceLimit(ctx, GL_MAX_COMPUTE_ATOMIC_COUNTERS) << ") 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         const bool                                      isES32                  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
804         map<string, string>                     args;
805
806         args["GLSL_VERSION_STRING"]                                     =       isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
807         args["GLSL_TESS_EXTENSION_STRING"]                      =       isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
808         args["COMPUTE_BUILT_IN_CONSTANTS_STRING"]       =       "       gl_MaxComputeWorkGroupCount       = ivec3(65535, 65535, 65535);\n"
809                                                                                                         "       gl_MaxComputeWorkGroupCount       = ivec3(1024, 1024, 64);\n"
810                                                                                                         "       gl_MaxComputeWorkGroupSize        = ivec3(512);\n"
811                                                                                                         "       gl_MaxComputeUniformComponents    = 512;\n"
812                                                                                                         "       gl_MaxComputeTextureImageUnits    = 16;\n"
813                                                                                                         "       gl_MaxComputeImageUniforms        = 8;\n"
814                                                                                                         "       gl_MaxComputeAtomicCounters       = 8;\n"
815                                                                                                         "       gl_MaxComputeAtomicCounterBuffers = 1;\n";
816
817         const glu::VertexSource                                 vertSource              (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_VERTEX)).specialize(args));
818         const glu::FragmentSource                               fragSource              (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_FRAGMENT)).specialize(args));
819         const glu::TessellationControlSource    tessCtrlSource  (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_TESSELLATION_CONTROL)).specialize(args));
820         const glu::TessellationEvaluationSource tessEvalSource  (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_TESSELLATION_EVALUATION)).specialize(args));
821         const glu::GeometrySource                               geometrySource  (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_GEOMETRY)).specialize(args));
822         const glu::ComputeSource                                computeSource   (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_COMPUTE)).specialize(args));
823
824         glu::ShaderProgram      vertProgram             (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << vertSource);
825         glu::ShaderProgram      fragProgram             (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << fragSource);
826         glu::ShaderProgram      tessCtrlProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource);
827         glu::ShaderProgram      tessEvalProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource);
828         glu::ShaderProgram      geometryProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << geometrySource);
829         glu::ShaderProgram      computeProgram  (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << computeSource);
830
831         ctx.beginSection("A compile time is generated if compute built-in constants provided in all shaders are written to.");
832         verifyCompileError(ctx, vertProgram, glu::SHADERTYPE_VERTEX);
833         verifyCompileError(ctx, fragProgram, glu::SHADERTYPE_FRAGMENT);
834         verifyCompileError(ctx, tessCtrlProgram, glu::SHADERTYPE_TESSELLATION_CONTROL);
835         verifyCompileError(ctx, tessEvalProgram, glu::SHADERTYPE_TESSELLATION_EVALUATION);
836         verifyCompileError(ctx, geometryProgram, glu::SHADERTYPE_GEOMETRY);
837         verifyCompileError(ctx, computeProgram, glu::SHADERTYPE_COMPUTE);
838         ctx.endSection();
839 }
840
841 } // anonymous
842
843 std::vector<FunctionContainer> getNegativeComputeTestFunctions (void)
844 {
845         const FunctionContainer funcs[] =
846         {
847                 { program_not_active,                                   "program_not_active",                                   "Use dispatch commands with no active program"                                                                  },
848                 { invalid_program_query,                                "invalid_program_query",                                "Querying GL_COMPUTE_WORK_GROUP_SIZE with glGetProgramiv() on invalid programs" },
849                 { invalid_dispatch_compute_indirect,    "invalid_dispatch_compute_indirect",    "Invalid glDispatchComputeIndirect usage"                                                                               },
850                 { invalid_maximum_work_group_counts,    "invalid_maximum_work_group_counts",    "Maximum workgroup counts for dispatch commands"                                                                },
851                 { invalid_maximum_work_group_sizes,             "invalid_maximum_work_group_sizes",             "Maximum local workgroup sizes declared in compute shaders"                                             },
852                 { invalid_layout_qualifiers,                    "invalid_layout_qualifiers",                    "Invalid layout qualifiers in compute shaders"                                                                  },
853                 { invalid_write_built_in_constants,             "invalid_write_built_in_constants",             "Invalid writes to built-in compute shader constants"                                                   },
854                 { exceed_uniform_block_limit,                   "exceed_uniform_block_limit",                   "Link error when shader exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS"                                  },
855                 { exceed_shader_storage_block_limit,    "exceed_shader_storage_block_limit",    "Link error when shader exceeds GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"                   },
856                 { exceed_texture_image_units_limit,             "exceed_texture_image_units_limit",             "Link error when shader exceeds GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"                             },
857                 { exceed_image_uniforms_limit,                  "exceed_image_uniforms_limit",                  "Link error when shader exceeds GL_MAX_COMPUTE_IMAGE_UNIFORMS"                                  },
858                 { exceed_shared_memory_size_limit,              "exceed_shared_memory_size_limit",              "Link error when shader exceeds GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"                              },
859                 { exceed_uniform_components_limit,              "exceed_uniform_components_limit",              "Link error when shader exceeds GL_MAX_COMPUTE_UNIFORM_COMPONENTS"                              },
860                 { exceed_atomic_counter_buffer_limit,   "exceed_atomic_counter_buffer_limit",   "Link error when shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"                  },
861                 { exceed_atomic_counters_limit,                 "exceed_atomic_counters_limit",                 "Link error when shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTERS"                                 },
862         };
863
864         return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
865 }
866
867 } // NegativeTestShared
868 } // Functional
869 } // gles31
870 } // deqp