Add new compute negative coverage tests
authorJohn Richardson <john.richardson@mobica.com>
Mon, 6 Feb 2017 11:28:21 +0000 (11:28 +0000)
committerMika Isojärvi <misojarvi@google.com>
Thu, 6 Jul 2017 19:34:15 +0000 (12:34 -0700)
Test groups added to:
- dEQP-GLES31.functional.debug.negative_coverage.*.compute (new)

New tests:
- program_not_active

- invalid_program_query
- invalid_dispatch_compute_indirect
- invalid_maximum_work_group_counts
- invalid_maximum_work_group_sizes
- invalid_layout_qualifiers
- invalid_write_built_in_constants

- exceed_uniform_block_limit
- exceed_shader_storage_block_limit
- exceed_texture_image_units_limit
- exceed_image_uniforms_limit
- exceed_shared_memory_size_limit
- exceed_uniform_components_limit
- exceed_atomic_counter_buffer_limit
- exceed_atomic_counters_limit

Change-Id: Ifd798652df3b138e174c1d9408b6ecdb003ce7f9

Android.mk
android/cts/master/gles31-master.txt
modules/gles31/functional/CMakeLists.txt
modules/gles31/functional/es31fDebugTests.cpp
modules/gles31/functional/es31fNegativeComputeTests.cpp [new file with mode: 0644]
modules/gles31/functional/es31fNegativeComputeTests.hpp [new file with mode: 0644]

index be25b8f..461146f 100644 (file)
@@ -587,6 +587,7 @@ LOCAL_SRC_FILES := \
        modules/gles31/functional/es31fNegativeFragmentApiTests.cpp \
        modules/gles31/functional/es31fNegativePreciseTests.cpp \
        modules/gles31/functional/es31fNegativeAdvancedBlendEquationTests.cpp \
+       modules/gles31/functional/es31fNegativeComputeTests.cpp \
        modules/gles31/functional/es31fNegativeShaderApiTests.cpp \
        modules/gles31/functional/es31fNegativeShaderDirectiveTests.cpp \
        modules/gles31/functional/es31fNegativeShaderFunctionTests.cpp \
index f42b33d..3d99919 100644 (file)
@@ -16804,6 +16804,21 @@ dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.invalid_pr
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.get_programiv
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.invalid_program_queries
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.tessellation_control_invalid_vertex_count
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.program_not_active
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.invalid_program_query
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.invalid_dispatch_compute_indirect
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.invalid_maximum_work_group_counts
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.invalid_maximum_work_group_sizes
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.invalid_layout_qualifiers
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.invalid_write_built_in_constants
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_uniform_block_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_shader_storage_block_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_texture_image_units_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_image_uniforms_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_shared_memory_size_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_uniform_components_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_atomic_counter_buffer_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_atomic_counters_limit
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.bind_buffer
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.delete_buffers
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.gen_buffers
@@ -17280,6 +17295,21 @@ dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.invalid_program_
 dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.get_programiv
 dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.invalid_program_queries
 dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.tessellation_control_invalid_vertex_count
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.program_not_active
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.invalid_program_query
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.invalid_dispatch_compute_indirect
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.invalid_maximum_work_group_counts
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.invalid_maximum_work_group_sizes
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.invalid_layout_qualifiers
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.invalid_write_built_in_constants
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_uniform_block_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_shader_storage_block_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_texture_image_units_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_image_uniforms_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_shared_memory_size_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_uniform_components_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_atomic_counter_buffer_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_atomic_counters_limit
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.bind_buffer
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.delete_buffers
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.gen_buffers
@@ -17754,6 +17784,21 @@ dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.invalid_pr
 dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.get_programiv
 dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.invalid_program_queries
 dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.tessellation_control_invalid_vertex_count
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.program_not_active
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.invalid_program_query
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.invalid_dispatch_compute_indirect
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.invalid_maximum_work_group_counts
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.invalid_maximum_work_group_sizes
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.invalid_layout_qualifiers
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.invalid_write_built_in_constants
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_uniform_block_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_shader_storage_block_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_texture_image_units_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_image_uniforms_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_shared_memory_size_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_uniform_components_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_atomic_counter_buffer_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_atomic_counters_limit
 dEQP-GLES31.functional.debug.externally_generated.application_messages
 dEQP-GLES31.functional.debug.externally_generated.third_party_messages
 dEQP-GLES31.functional.debug.externally_generated.push_pop_stack
index 3b5bcb3..bf566fd 100644 (file)
@@ -185,6 +185,8 @@ set(DEQP_GLES31_FUNCTIONAL_SRCS
        es31fNegativeSSBOBlockTests.hpp
        es31fDrawElementsBaseVertexTests.cpp
        es31fDrawElementsBaseVertexTests.hpp
+       es31fNegativeComputeTests.cpp
+       es31fNegativeComputeTests.hpp
        )
 
 add_library(deqp-gles31-functional STATIC ${DEQP_GLES31_FUNCTIONAL_SRCS})
index d41addb..f2e65b3 100644 (file)
@@ -39,6 +39,7 @@
 #include "es31fNegativeAdvancedBlendEquationTests.hpp"
 #include "es31fNegativeShaderStorageTests.hpp"
 #include "es31fNegativeTessellationTests.hpp"
+#include "es31fNegativeComputeTests.hpp"
 
 #include "deUniquePtr.hpp"
 #include "deRandom.hpp"
@@ -2960,6 +2961,7 @@ void DebugTests::init (void)
        const vector<FunctionContainer> preciseFuncs                     = wrapCoreFunctions(NegativeTestShared::getNegativePreciseTestFunctions());
        const vector<FunctionContainer> advancedBlendFuncs               = wrapCoreFunctions(NegativeTestShared::getNegativeAdvancedBlendEquationTestFunctions());
        const vector<FunctionContainer> shaderStorageFuncs               = wrapCoreFunctions(NegativeTestShared::getNegativeShaderStorageTestFunctions());
+       const vector<FunctionContainer> computeFuncs                     = wrapCoreFunctions(NegativeTestShared::getNegativeComputeTestFunctions());
        const vector<FunctionContainer> externalFuncs                    = getUserMessageFuncs();
 
        {
@@ -3068,6 +3070,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "advanced_blend",                         "Negative Advanced Blend Equation Cases",                       advancedBlendFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_storage",                         "Negative Shader Storage Cases",                                        shaderStorageFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "tessellation",                           "Negative Tessellation Cases",                                          tessellationFuncs));
+                       host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "compute",                                        "Negative Compute Cases",                                                       computeFuncs));
                }
 
                {
@@ -3093,6 +3096,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "advanced_blend",                      "Negative Advanced Blend Equation Cases",                       advancedBlendFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_storage",                      "Negative Shader Storage Cases",                                        shaderStorageFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "tessellation",                        "Negative Tessellation Cases",                                          tessellationFuncs));
+                       host->addChild(createChildCases(CASETYPE_LOG, m_context, "compute",                                     "Negative Compute Cases",                                                       computeFuncs));
                }
 
                {
@@ -3118,6 +3122,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "advanced_blend",                         "Negative Advanced Blend Equation Cases",                       advancedBlendFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_storage",                         "Negative Shader Storage Cases",                                        shaderStorageFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "tessellation",                           "Negative Tessellation Cases",                                          tessellationFuncs));
+                       host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "compute",                                        "Negative Compute Cases",                                                       computeFuncs));
                }
        }
 
diff --git a/modules/gles31/functional/es31fNegativeComputeTests.cpp b/modules/gles31/functional/es31fNegativeComputeTests.cpp
new file mode 100644 (file)
index 0000000..c0c36bc
--- /dev/null
@@ -0,0 +1,870 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Negative Compute tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fNegativeComputeTests.hpp"
+#include "gluContextInfo.hpp"
+#include "gluShaderProgram.hpp"
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+#include "tcuStringTemplate.hpp"
+
+namespace deqp
+{
+
+using std::string;
+using std::map;
+
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+namespace
+{
+
+using tcu::TestLog;
+using namespace glw;
+
+static const char* const vertexShaderSource                    =       "${GLSL_VERSION_STRING}\n"
+                                                                                                               "\n"
+                                                                                                               "void main (void)\n"
+                                                                                                               "{\n"
+                                                                                                               "       gl_Position = vec4(0.0);\n"
+                                                                                                               "}\n";
+
+static const char* const fragmentShaderSource          =       "${GLSL_VERSION_STRING}\n"
+                                                                                                               "precision mediump float;\n"
+                                                                                                               "layout(location = 0) out mediump vec4 fragColor;\n"
+                                                                                                               "\n"
+                                                                                                               "void main (void)\n"
+                                                                                                               "{\n"
+                                                                                                               "       fragColor = vec4(1.0);\n"
+                                                                                                               "}\n";
+
+static const char* const computeShaderSource           =       "${GLSL_VERSION_STRING}\n"
+                                                                                                               "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                                                               "void main (void)\n"
+                                                                                                               "{\n"
+                                                                                                               "}\n";
+
+static const char* const invalidComputeShaderSource    =       "${GLSL_VERSION_STRING}\n"
+                                                                                                               "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                                                               "void main (void)\n"
+                                                                                                               "{\n"
+                                                                                                               "       highp uint var = -1;\n" // error
+                                                                                                               "}\n";
+
+int getResourceLimit (NegativeTestContext& ctx, GLenum resource)
+{
+       int limit = 0;
+       ctx.glGetIntegerv(resource, &limit);
+
+       return limit;
+}
+
+void verifyLinkError (NegativeTestContext& ctx, const glu::ShaderProgram& program)
+{
+       bool testFailed = false;
+
+       tcu::TestLog& log = ctx.getLog();
+       log << program;
+
+       testFailed = program.getProgramInfo().linkOk;
+
+       if (testFailed)
+       {
+               const char* const message("Program was not expected to link.");
+               log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+               ctx.fail(message);
+       }
+}
+
+void verifyCompileError (NegativeTestContext& ctx, const glu::ShaderProgram& program, glu::ShaderType shaderType)
+{
+       bool testFailed = false;
+
+       tcu::TestLog& log = ctx.getLog();
+       log << program;
+
+       testFailed = program.getShaderInfo(shaderType).compileOk;
+
+       if (testFailed)
+       {
+               const char* const message("Program was not expected to compile.");
+               log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+               ctx.fail(message);
+       }
+}
+
+string generateComputeShader (NegativeTestContext& ctx, const string& shaderDeclarations, const string& shaderBody)
+{
+       const bool                      isES32                  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       const char* const       shaderVersion   = isES32
+                                                                               ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES)
+                                                                               : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       std::ostringstream compShaderSource;
+
+       compShaderSource        <<      shaderVersion << "\n"
+                                               <<      "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                               <<      shaderDeclarations << "\n"
+                                               <<      "void main (void)\n"
+                                               <<      "{\n"
+                                               <<      shaderBody
+                                               <<      "}\n";
+
+       return compShaderSource.str();
+}
+
+string genBuiltInSource (glu::ShaderType shaderType)
+{
+       std::ostringstream              source;
+       source << "${GLSL_VERSION_STRING}\n";
+
+       switch (shaderType)
+       {
+               case glu::SHADERTYPE_VERTEX:
+               case glu::SHADERTYPE_FRAGMENT:
+                       break;
+
+               case glu::SHADERTYPE_COMPUTE:
+                       source << "layout (local_size_x = 1) in;\n";
+                       break;
+
+               case glu::SHADERTYPE_GEOMETRY:
+                       source << "layout(points) in;\n"
+                                  << "layout(line_strip, max_vertices = 3) out;\n";
+                       break;
+
+               case glu::SHADERTYPE_TESSELLATION_CONTROL:
+                       source << "${GLSL_TESS_EXTENSION_STRING}\n"
+                                  << "layout(vertices = 10) out;\n";
+                       break;
+
+               case glu::SHADERTYPE_TESSELLATION_EVALUATION:
+                       source << "${GLSL_TESS_EXTENSION_STRING}\n"
+                                  << "layout(triangles) in;\n";
+                       break;
+
+               default:
+                       DE_FATAL("Unknown shader type");
+                       break;
+       }
+
+       source  << "\n"
+                       << "void main(void)\n"
+                       << "{\n"
+                       << "${COMPUTE_BUILT_IN_CONSTANTS_STRING}"
+                       << "}\n";
+
+       return source.str();
+}
+
+void exceed_uniform_block_limit (NegativeTestContext& ctx)
+{
+       std::ostringstream shaderDecl;
+       std::ostringstream shaderBody;
+
+       shaderDecl      << "layout(std140, binding = 0) uniform Block\n"
+                               << "{\n"
+                               << "    highp vec4 val;\n"
+                               << "} block[" << getResourceLimit(ctx, GL_MAX_COMPUTE_UNIFORM_BLOCKS) + 1 << "];\n";
+
+       glu::ShaderProgram      program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
+
+       ctx.beginSection("Link error is generated if a compute shader exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS.");
+       verifyLinkError(ctx, program);
+       ctx.endSection();
+}
+
+void exceed_shader_storage_block_limit (NegativeTestContext& ctx)
+{
+       std::ostringstream shaderDecl;
+       std::ostringstream shaderBody;
+
+       shaderDecl      << "layout(std140, binding = 0) buffer Block\n"
+                               << "{\n"
+                               << "    highp vec4 val;\n"
+                               << "} block[" << getResourceLimit(ctx, GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS) + 1 << "];\n";
+
+       glu::ShaderProgram      program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
+
+       ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS.");
+       verifyLinkError(ctx, program);
+       ctx.endSection();
+}
+
+void exceed_texture_image_units_limit (NegativeTestContext& ctx)
+{
+       const int                       limit                   = getResourceLimit(ctx, GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS) + 1;
+       std::ostringstream      shaderDecl;
+       std::ostringstream      shaderBody;
+
+       shaderDecl      << "layout(binding = 0) "
+                               << "uniform highp sampler2D u_sampler[" << limit + 1 << "];\n"
+                               << "\n"
+                               << "layout(binding = 0) buffer Output {\n"
+                               << "    vec4 values[ " << limit + 1 << " ];\n"
+                               << "} sb_out;\n";
+
+       for (int i = 0; i < limit + 1; ++i)
+               shaderBody      << "   sb_out.values[" << i << "] = texture(u_sampler[" << i << "], vec2(1.0f));\n";
+
+       glu::ShaderProgram      program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
+
+       tcu::TestLog& log = ctx.getLog();
+       log << tcu::TestLog::Message << "Possible link error is generated if compute shader exceeds GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS." << tcu::TestLog::EndMessage;
+       log << program;
+
+       if (program.getProgramInfo().linkOk)
+       {
+               log << tcu::TestLog::Message << "Quality Warning: program was not expected to link." << tcu::TestLog::EndMessage;
+               ctx.glUseProgram(program.getProgram());
+               ctx.expectError(GL_NO_ERROR);
+
+               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");
+               ctx.glDispatchCompute(1, 1, 1);
+               ctx.expectError(GL_INVALID_VALUE);
+               ctx.endSection();
+       }
+}
+
+void exceed_image_uniforms_limit (NegativeTestContext& ctx)
+{
+       const int                       limit = getResourceLimit(ctx, GL_MAX_COMPUTE_IMAGE_UNIFORMS);
+       std::ostringstream      shaderDecl;
+       std::ostringstream      shaderBody;
+
+       shaderDecl      << "layout(rgba8, binding = 0) "
+                               << "uniform readonly highp image2D u_image[" << limit + 1 << "];\n"
+                               << "\n"
+                               << "layout(binding = 0) buffer Output {\n"
+                               << "    float values[" << limit + 1 << "];\n"
+                               << "} sb_out;\n";
+
+       for (int i = 0; i < limit + 1; ++i)
+               shaderBody      << "    sb_out.values[" << i << "]" << "  = imageLoad(u_image[" << i << "], ivec2(gl_GlobalInvocationID.xy)).x;\n";
+
+       glu::ShaderProgram      program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
+
+       ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_IMAGE_UNIFORMS.");
+       verifyLinkError(ctx, program);
+       ctx.endSection();
+}
+
+void exceed_shared_memory_size_limit (NegativeTestContext& ctx)
+{
+       const int                       limit                           = getResourceLimit(ctx, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
+       const long                      numberOfElements        = limit / sizeof(GLuint);
+       std::ostringstream      shaderDecl;
+       std::ostringstream      shaderBody;
+
+       shaderDecl      << "shared uint values[" << numberOfElements + 1 << "];\n"
+                               << "\n"
+                               << "layout(binding = 0) buffer Output {\n"
+                               << "    uint values;\n"
+                               << "} sb_out;\n";
+
+       shaderBody      << "    sb_out.values = values[" << numberOfElements << "];\n";
+
+       glu::ShaderProgram      program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
+
+       ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_SHARED_MEMORY_SIZE.");
+       verifyLinkError(ctx, program);
+       ctx.endSection();
+}
+
+void exceed_uniform_components_limit (NegativeTestContext& ctx)
+{
+       const int                       limit = getResourceLimit(ctx, GL_MAX_COMPUTE_UNIFORM_COMPONENTS);
+       std::ostringstream      shaderDecl;
+       std::ostringstream      shaderBody;
+
+       shaderDecl      << "uniform highp uint u_value[" << limit + 1 << "];\n"
+                               << "\n"
+                               << "layout(binding = 0) buffer Output {\n"
+                               << "    uint values[2];\n"
+                               << "} sb_out;\n";
+
+       shaderBody << "    sb_out.values[0] = u_value[" << limit << "];\n";
+       shaderBody << "    sb_out.values[1] = u_value[0];\n";
+
+       glu::ShaderProgram      program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
+
+       ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_UNIFORM_COMPONENTS.");
+       verifyLinkError(ctx, program);
+       ctx.endSection();
+}
+
+void exceed_atomic_counter_buffer_limit (NegativeTestContext& ctx)
+{
+       const int                       limit = getResourceLimit(ctx, GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS);
+       std::ostringstream      shaderDecl;
+       std::ostringstream      shaderBody;
+
+       for (int i = 0; i < limit + 1; ++i)
+       {
+               shaderDecl      << "layout(binding = " << i << ") "
+                                       << "uniform atomic_uint u_atomic" << i << ";\n";
+
+               if (i == 0)
+                       shaderBody      << "    uint oldVal = atomicCounterIncrement(u_atomic" << i << ");\n";
+               else
+                       shaderBody      << "    oldVal = atomicCounterIncrement(u_atomic" << i << ");\n";
+       }
+
+       shaderBody      << "    sb_out.value = oldVal;\n";
+
+       shaderDecl      << "\n"
+                               << "layout(binding = 0) buffer Output {\n"
+                               << "    uint value;\n"
+                               << "} sb_out;\n";
+
+       glu::ShaderProgram      program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
+
+       ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS.");
+       verifyLinkError(ctx, program);
+       ctx.endSection();
+}
+
+void exceed_atomic_counters_limit (NegativeTestContext& ctx)
+{
+       std::ostringstream      shaderDecl;
+       std::ostringstream      shaderBody;
+
+       shaderDecl      << "layout(binding = 0, offset = 0) uniform atomic_uint u_atomic0;\n"
+                               << "layout(binding = 0, offset = " << sizeof(GLuint) * getResourceLimit(ctx, GL_MAX_COMPUTE_ATOMIC_COUNTERS) << ") uniform atomic_uint u_atomic1;\n"
+                               << "\n"
+                               << "layout(binding = 0) buffer Output {\n"
+                               << "    uint value;\n"
+                               << "} sb_out;\n";
+
+       shaderBody      << "    uint oldVal = 0u;\n"
+                               << "    oldVal = atomicCounterIncrement(u_atomic0);\n"
+                               << "    oldVal = atomicCounterIncrement(u_atomic1);\n"
+                               << "    sb_out.value = oldVal;\n";
+
+       glu::ShaderProgram      program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::ComputeSource(generateComputeShader(ctx, shaderDecl.str(), shaderBody.str())));
+
+       ctx.beginSection("Link error is generated if compute shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTERS.");
+       verifyLinkError(ctx, program);
+       ctx.endSection();
+}
+
+void program_not_active (NegativeTestContext& ctx)
+{
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       const glu::VertexSource         vertSource(tcu::StringTemplate(vertexShaderSource).specialize(args));
+       const glu::FragmentSource       fragSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
+
+       glu::ProgramPipeline            pipeline(ctx.getRenderContext());
+
+       glu::ShaderProgram                      vertProgram     (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << vertSource);
+       glu::ShaderProgram                      fragProgram     (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << fragSource);
+
+       tcu::TestLog& log                       = ctx.getLog();
+       log << vertProgram << fragProgram;
+
+       if (!vertProgram.isOk() || !fragProgram.isOk())
+               TCU_THROW(InternalError, "failed to build program");
+
+       ctx.glBindProgramPipeline(pipeline.getPipeline());
+       ctx.expectError(GL_NO_ERROR);
+
+       ctx.beginSection("Program not set at all");
+       {
+               ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchCompute if there is no active program for the compute shader stage.");
+               ctx.glDispatchCompute(1, 1, 1);
+               ctx.expectError(GL_INVALID_OPERATION);
+               ctx.endSection();
+
+               ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if there is no active program for the compute shader stage.");
+               GLintptr indirect = 0;
+               ctx.glDispatchComputeIndirect(indirect);
+               ctx.expectError(GL_INVALID_OPERATION);
+               ctx.endSection();
+       }
+       ctx.endSection();
+
+       ctx.beginSection("Program contains graphic pipeline stages");
+       {
+               ctx.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vertProgram.getProgram());
+               ctx.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, fragProgram.getProgram());
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchCompute if there is no active program for the compute shader stage.");
+               ctx.glDispatchCompute(1, 1, 1);
+               ctx.expectError(GL_INVALID_OPERATION);
+               ctx.endSection();
+
+               ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if there is no active program for the compute shader stage.");
+               GLintptr indirect = 0;
+               ctx.glDispatchComputeIndirect(indirect);
+               ctx.expectError(GL_INVALID_OPERATION);
+               ctx.endSection();
+       }
+       ctx.endSection();
+
+       ctx.glBindProgramPipeline(0);
+       ctx.expectError(GL_NO_ERROR);
+}
+
+void invalid_program_query (NegativeTestContext& ctx)
+{
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       GLint data[3] = { 0, 0, 0 };
+
+       ctx.beginSection("Compute shader that does not link");
+       {
+               const glu::ComputeSource        compSource(tcu::StringTemplate(invalidComputeShaderSource).specialize(args));
+               glu::ShaderProgram                      invalidComputeProgram (ctx.getRenderContext(), glu::ProgramSources() << compSource);
+
+               tcu::TestLog& log = ctx.getLog();
+               log << invalidComputeProgram;
+
+               if (invalidComputeProgram.isOk())
+                       TCU_THROW(InternalError, "program should not of built");
+
+               ctx.beginSection("GL_INVALID_OPERATION is generated if GL_COMPUTE_WORK_GROUP_SIZE is queried for a program which has not been linked properly.");
+               ctx.glGetProgramiv(invalidComputeProgram.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, &data[0]);
+               ctx.expectError(GL_INVALID_OPERATION);
+               ctx.endSection();
+
+               ctx.glUseProgram(0);
+       }
+       ctx.endSection();
+
+       ctx.beginSection("Compute shader not present");
+       {
+               const glu::VertexSource         vertSource(tcu::StringTemplate(vertexShaderSource).specialize(args));
+               const glu::FragmentSource       fragSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
+               glu::ShaderProgram                      graphicsPipelineProgram (ctx.getRenderContext(), glu::ProgramSources() << vertSource << fragSource);
+
+               tcu::TestLog& log = ctx.getLog();
+               log << graphicsPipelineProgram;
+
+               if (!graphicsPipelineProgram.isOk())
+                       TCU_THROW(InternalError, "failed to build program");
+
+               ctx.beginSection("GL_INVALID_OPERATION is generated if GL_COMPUTE_WORK_GROUP_SIZE is queried for a program which has not been linked properly.");
+               ctx.glGetProgramiv(graphicsPipelineProgram.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, &data[0]);
+               ctx.expectError(GL_INVALID_OPERATION);
+               ctx.endSection();
+
+               ctx.glUseProgram(0);
+       }
+       ctx.endSection();
+}
+
+void invalid_dispatch_compute_indirect (NegativeTestContext& ctx)
+{
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       const glu::ComputeSource        compSource(tcu::StringTemplate(computeShaderSource).specialize(args));
+       glu::ShaderProgram                      program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
+
+       tcu::TestLog& log = ctx.getLog();
+       log << program;
+
+       if (!program.isOk())
+               TCU_THROW(InternalError, "failed to build program");
+
+       ctx.glUseProgram(program.getProgram());
+       ctx.expectError(GL_NO_ERROR);
+
+       static const struct
+       {
+               GLuint numGroupsX;
+               GLuint numGroupsY;
+               GLuint numGroupsZ;
+       } data = {0, 0, 0};
+
+       {
+               GLuint buffer;
+               ctx.glGenBuffers(1, &buffer);
+               ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if zero is bound to GL_DISPATCH_INDIRECT_BUFFER.");
+               GLintptr indirect = 0;
+               ctx.glDispatchComputeIndirect(indirect);
+               ctx.expectError(GL_INVALID_OPERATION);
+               ctx.endSection();
+
+               ctx.glDeleteBuffers(1, &buffer);
+       }
+
+       {
+               GLuint buffer;
+               ctx.glGenBuffers(1, &buffer);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(data), &data, GL_STATIC_DRAW);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.beginSection("GL_INVALID_OPERATION is generated by glDispatchComputeIndirect if data is sourced beyond the end of the buffer object.");
+               GLintptr indirect = 1 << 10;
+               ctx.glDispatchComputeIndirect(indirect);
+               ctx.expectError(GL_INVALID_OPERATION);
+               ctx.endSection();
+
+               ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
+               ctx.glDeleteBuffers(1, &buffer);
+       }
+
+       {
+               ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchComputeIndirect if the value of indirect is less than zero.");
+               GLintptr indirect = -1;
+               ctx.glDispatchComputeIndirect(indirect);
+               ctx.expectError(GL_INVALID_VALUE);
+               ctx.endSection();
+       }
+
+       {
+               GLuint buffer;
+               ctx.glGenBuffers(1, &buffer);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(data), &data, GL_STATIC_DRAW);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchComputeIndirect if indirect is not a multiple of the size, in basic machine units, of uint.");
+               GLintptr indirect = sizeof(data) + 1;
+               ctx.glDispatchComputeIndirect(indirect);
+               ctx.expectError(GL_INVALID_VALUE);
+               ctx.endSection();
+
+               ctx.glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
+               ctx.glDeleteBuffers(1, &buffer);
+       }
+}
+
+void invalid_maximum_work_group_counts (NegativeTestContext& ctx)
+{
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       const glu::ComputeSource        compSource(tcu::StringTemplate(computeShaderSource).specialize(args));
+       glu::ShaderProgram                      program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
+
+       tcu::TestLog& log = ctx.getLog();
+       log << program;
+
+       if (!program.isOk())
+               TCU_THROW(InternalError, "failed to build program");
+
+       ctx.glUseProgram(program.getProgram());
+       ctx.expectError(GL_NO_ERROR);
+
+       GLint workGroupCountX;
+       ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)0, &workGroupCountX);
+       ctx.expectError(GL_NO_ERROR);
+
+       ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsX> array is larger than the maximum work group count for the x dimension.");
+       ctx.glDispatchCompute(workGroupCountX+1, 1, 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       GLint workGroupCountY;
+       ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)1, &workGroupCountY);
+       ctx.expectError(GL_NO_ERROR);
+
+       ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsY> array is larger than the maximum work group count for the y dimension.");
+       ctx.glDispatchCompute(1, workGroupCountY+1, 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       GLint workGroupCountZ;
+       ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, (GLuint)2, &workGroupCountZ);
+       ctx.expectError(GL_NO_ERROR);
+
+       ctx.beginSection("GL_INVALID_VALUE is generated by glDispatchCompute if <numGroupsZ> array is larger than the maximum work group count for the z dimension.");
+       ctx.glDispatchCompute(1, 1, workGroupCountZ+1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+}
+
+void invalid_maximum_work_group_sizes (NegativeTestContext& ctx)
+{
+       GLint maxWorkGroupSizeX;
+       ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)0, &maxWorkGroupSizeX);
+       ctx.expectError(GL_NO_ERROR);
+
+       GLint maxWorkGroupSizeY;
+       ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)1, &maxWorkGroupSizeY);
+       ctx.expectError(GL_NO_ERROR);
+
+       GLint maxWorkGroupSizeZ;
+       ctx.glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, (GLuint)2, &maxWorkGroupSizeZ);
+       ctx.expectError(GL_NO_ERROR);
+
+       GLint maxWorkGroupInvocations;
+       ctx.glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &maxWorkGroupInvocations);
+       ctx.expectError(GL_NO_ERROR);
+
+       DE_ASSERT((maxWorkGroupSizeX * maxWorkGroupSizeY * maxWorkGroupSizeZ) > maxWorkGroupInvocations );
+
+       const bool                              isES32                  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       const char* const               shaderVersion   = isES32
+                                                                                       ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES)
+                                                                                       : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       static const struct
+       {
+               GLint x;
+               GLint y;
+               GLint z;
+       } localWorkGroupSizeCases[] =
+       {
+               {       maxWorkGroupSizeX+1,    1,                                              1                                               },
+               {       1,                                              maxWorkGroupSizeY+1,    1                                               },
+               {       1,                                              1,                                              maxWorkGroupSizeZ+1             },
+               {       maxWorkGroupSizeX,              maxWorkGroupSizeY,              maxWorkGroupSizeZ               },
+       };
+
+       for (int testCase = 0; testCase < DE_LENGTH_OF_ARRAY(localWorkGroupSizeCases); ++testCase)
+       {
+               std::ostringstream compShaderSource;
+
+               compShaderSource        <<      shaderVersion << "\n"
+                                                       <<      "layout(local_size_x = " << localWorkGroupSizeCases[testCase].x << ", local_size_y = " << localWorkGroupSizeCases[testCase].y << ", local_size_z = " << localWorkGroupSizeCases[testCase].z << ") in;\n"
+                                                       <<      "void main (void)\n"
+                                                       <<      "{\n"
+                                                       <<      "}\n";
+
+               const glu::ComputeSource        compSource(compShaderSource.str());
+               glu::ShaderProgram                      program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
+
+               if (testCase == DE_LENGTH_OF_ARRAY(localWorkGroupSizeCases)-1)
+               {
+                       bool testFailed = false;
+                       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.");
+
+                       ctx.getLog() << program;
+                       testFailed = (program.getProgramInfo().linkOk) && (program.getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk);
+
+                       if (testFailed)
+                       {
+                               const char* const message("Program was not expected to compile or link.");
+                               ctx.getLog() << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+                               ctx.fail(message);
+                       }
+               }
+               else
+               {
+                       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.");
+                       verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE);
+               }
+
+               ctx.endSection();
+       }
+}
+
+void invalid_layout_qualifiers (NegativeTestContext& ctx)
+{
+       const bool                              isES32                  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       const char* const               shaderVersion   = isES32
+                                                                                       ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES)
+                                                                                       : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       {
+               std::ostringstream compShaderSource;
+               compShaderSource        <<      shaderVersion << "\n"
+                                                       <<      "void main (void)\n"
+                                                       <<      "{\n"
+                                                       <<      "}\n";
+
+               const glu::ComputeSource        compSource(compShaderSource.str());
+               glu::ShaderProgram                      program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
+
+               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.");
+               verifyLinkError(ctx, program);
+               ctx.endSection();
+       }
+
+       {
+               std::ostringstream compShaderSource;
+               compShaderSource        <<      shaderVersion << "\n"
+                                                       <<      "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                       <<      "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
+                                                       <<      "void main (void)\n"
+                                                       <<      "{\n"
+                                                       <<      "}\n";
+
+               const glu::ComputeSource        compSource(compShaderSource.str());
+               glu::ShaderProgram                      program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
+
+               ctx.beginSection("A compile-time error is generated if a local work group size qualifier is declared more than once in the same shader.");
+               verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE);
+               ctx.endSection();
+       }
+
+       {
+               std::ostringstream compShaderSource;
+               compShaderSource        <<      shaderVersion << "\n"
+                                                       <<      "out mediump vec4 fragColor;\n"
+                                                       <<      "\n"
+                                                       <<      "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                       <<      "void main (void)\n"
+                                                       <<      "{\n"
+                                                       <<      "}\n";
+
+               const glu::ComputeSource        compSource(compShaderSource.str());
+               glu::ShaderProgram                      program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
+
+               ctx.beginSection("A compile-time error is generated if a user defined output variable is declared in a compute shader.");
+               verifyCompileError(ctx, program, glu::SHADERTYPE_COMPUTE);
+               ctx.endSection();
+       }
+
+       {
+               std::ostringstream compShaderSource;
+               compShaderSource        <<      shaderVersion << "\n"
+                                                       <<      "uvec3 gl_NumWorkGroups;\n"
+                                                       <<      "uvec3 gl_WorkGroupSize;\n"
+                                                       <<      "uvec3 gl_WorkGroupID;\n"
+                                                       <<      "uvec3 gl_LocalInvocationID;\n"
+                                                       <<      "uvec3 gl_GlobalInvocationID;\n"
+                                                       <<      "uvec3 gl_LocalInvocationIndex;\n"
+                                                       <<      "\n"
+                                                       <<      "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                       <<      "void main (void)\n"
+                                                       <<      "{\n"
+                                                       <<      "}\n";
+
+               const glu::ComputeSource        compSource(compShaderSource.str());
+               glu::ShaderProgram                      program(ctx.getRenderContext(), glu::ProgramSources() << compSource);
+
+               ctx.beginSection("A compile time or link error is generated if compute shader built-in variables are redeclared.");
+               bool testFailed = false;
+
+               tcu::TestLog& log = ctx.getLog();
+               log << program;
+
+               testFailed = (program.getProgramInfo().linkOk) && (program.getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk);
+
+               if (testFailed)
+               {
+                       const char* const message("Program was not expected to compile or link.");
+                       log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+                       ctx.fail(message);
+               }
+
+               ctx.endSection();
+       }
+}
+
+void invalid_write_built_in_constants (NegativeTestContext& ctx)
+{
+       const bool                                      isES32                  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       map<string, string>                     args;
+
+       args["GLSL_VERSION_STRING"]                                     =       isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       args["GLSL_TESS_EXTENSION_STRING"]                      =       isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+       args["COMPUTE_BUILT_IN_CONSTANTS_STRING"]       =       "       gl_MaxComputeWorkGroupCount       = ivec3(65535, 65535, 65535);\n"
+                                                                                                       "       gl_MaxComputeWorkGroupCount       = ivec3(1024, 1024, 64);\n"
+                                                                                                       "       gl_MaxComputeWorkGroupSize        = ivec3(512);\n"
+                                                                                                       "       gl_MaxComputeUniformComponents    = 512;\n"
+                                                                                                       "       gl_MaxComputeTextureImageUnits    = 16;\n"
+                                                                                                       "       gl_MaxComputeImageUniforms        = 8;\n"
+                                                                                                       "       gl_MaxComputeAtomicCounters       = 8;\n"
+                                                                                                       "       gl_MaxComputeAtomicCounterBuffers = 1;\n";
+
+       const glu::VertexSource                                 vertSource              (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_VERTEX)).specialize(args));
+       const glu::FragmentSource                               fragSource              (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_FRAGMENT)).specialize(args));
+       const glu::TessellationControlSource    tessCtrlSource  (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_TESSELLATION_CONTROL)).specialize(args));
+       const glu::TessellationEvaluationSource tessEvalSource  (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_TESSELLATION_EVALUATION)).specialize(args));
+       const glu::GeometrySource                               geometrySource  (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_GEOMETRY)).specialize(args));
+       const glu::ComputeSource                                computeSource   (tcu::StringTemplate(genBuiltInSource(glu::SHADERTYPE_COMPUTE)).specialize(args));
+
+       glu::ShaderProgram      vertProgram             (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << vertSource);
+       glu::ShaderProgram      fragProgram             (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << fragSource);
+       glu::ShaderProgram      tessCtrlProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource);
+       glu::ShaderProgram      tessEvalProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource);
+       glu::ShaderProgram      geometryProgram (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << geometrySource);
+       glu::ShaderProgram      computeProgram  (ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << computeSource);
+
+       ctx.beginSection("A compile time is generated if compute built-in constants provided in all shaders are written to.");
+       verifyCompileError(ctx, vertProgram, glu::SHADERTYPE_VERTEX);
+       verifyCompileError(ctx, fragProgram, glu::SHADERTYPE_FRAGMENT);
+       verifyCompileError(ctx, tessCtrlProgram, glu::SHADERTYPE_TESSELLATION_CONTROL);
+       verifyCompileError(ctx, tessEvalProgram, glu::SHADERTYPE_TESSELLATION_EVALUATION);
+       verifyCompileError(ctx, geometryProgram, glu::SHADERTYPE_GEOMETRY);
+       verifyCompileError(ctx, computeProgram, glu::SHADERTYPE_COMPUTE);
+       ctx.endSection();
+}
+
+} // anonymous
+
+std::vector<FunctionContainer> getNegativeComputeTestFunctions (void)
+{
+       const FunctionContainer funcs[] =
+       {
+               { program_not_active,                                   "program_not_active",                                   "Use dispatch commands with no active program"                                                                  },
+               { invalid_program_query,                                "invalid_program_query",                                "Querying GL_COMPUTE_WORK_GROUP_SIZE with glGetProgramiv() on invalid programs" },
+               { invalid_dispatch_compute_indirect,    "invalid_dispatch_compute_indirect",    "Invalid glDispatchComputeIndirect usage"                                                                               },
+               { invalid_maximum_work_group_counts,    "invalid_maximum_work_group_counts",    "Maximum workgroup counts for dispatch commands"                                                                },
+               { invalid_maximum_work_group_sizes,             "invalid_maximum_work_group_sizes",             "Maximum local workgroup sizes declared in compute shaders"                                             },
+               { invalid_layout_qualifiers,                    "invalid_layout_qualifiers",                    "Invalid layout qualifiers in compute shaders"                                                                  },
+               { invalid_write_built_in_constants,             "invalid_write_built_in_constants",             "Invalid writes to built-in compute shader constants"                                                   },
+               { exceed_uniform_block_limit,                   "exceed_uniform_block_limit",                   "Link error when shader exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS"                                  },
+               { exceed_shader_storage_block_limit,    "exceed_shader_storage_block_limit",    "Link error when shader exceeds GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"                   },
+               { exceed_texture_image_units_limit,             "exceed_texture_image_units_limit",             "Link error when shader exceeds GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"                             },
+               { exceed_image_uniforms_limit,                  "exceed_image_uniforms_limit",                  "Link error when shader exceeds GL_MAX_COMPUTE_IMAGE_UNIFORMS"                                  },
+               { exceed_shared_memory_size_limit,              "exceed_shared_memory_size_limit",              "Link error when shader exceeds GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"                              },
+               { exceed_uniform_components_limit,              "exceed_uniform_components_limit",              "Link error when shader exceeds GL_MAX_COMPUTE_UNIFORM_COMPONENTS"                              },
+               { exceed_atomic_counter_buffer_limit,   "exceed_atomic_counter_buffer_limit",   "Link error when shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"                  },
+               { exceed_atomic_counters_limit,                 "exceed_atomic_counters_limit",                 "Link error when shader exceeds GL_MAX_COMPUTE_ATOMIC_COUNTERS"                                 },
+       };
+
+       return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fNegativeComputeTests.hpp b/modules/gles31/functional/es31fNegativeComputeTests.hpp
new file mode 100644 (file)
index 0000000..8b582c9
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _ES31FNEGATIVECOMPUTETESTS_HPP
+#define _ES31FNEGATIVECOMPUTETESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Negative Compute tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeComputeTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles3
+} // deqp
+
+#endif // _ES31FNEGATIVECOMPUTETESTS_HPP