ES31: Add missing checks for querying GL_COMPUTE_WORK_GROUP_SIZE

This patch adds missing checks for querying GL_COMPUTE_WORK_GROUP_SIZE
by glGetProgramiv.

When querying GL_COMPUTE_WORK_GROUP_SIZE, an INVALID_OPERATION error
should be generated when this program hasn't been linked successfully
or it doesn't contain any objects to form a compute shader.

BUG=angleproject:2324
TEST=angle_end2end_tests
     dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.invalid_program_query

Change-Id: I13dcebef8a0abede5c18a038d4cf915ee4164e2e
Reviewed-on: https://chromium-review.googlesource.com/933627
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h
index 2f751b4..fced380 100644
--- a/src/libANGLE/ErrorStrings.h
+++ b/src/libANGLE/ErrorStrings.h
@@ -134,6 +134,7 @@
 ERRMSG(NegativeSize, "Cannot have negative height or width.");
 ERRMSG(NegativeStart, "Cannot have negative start.");
 ERRMSG(NegativeStride, "Cannot have negative stride.");
+ERRMSG(NoActiveComputeShaderStage, "No active compute shader stage in this program.");
 ERRMSG(NoActiveProgramWithComputeShader, "No active program for the compute shader stage.");
 ERRMSG(NoSuchPath, "No such path object.");
 ERRMSG(NoTransformFeedbackOutputVariables,
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index fd00b7b..90a65de 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -4168,7 +4168,6 @@
             break;
 
         case GL_PROGRAM_SEPARABLE:
-        case GL_COMPUTE_WORK_GROUP_SIZE:
         case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
             if (context->getClientVersion() < Version(3, 1))
             {
@@ -4177,6 +4176,29 @@
             }
             break;
 
+        case GL_COMPUTE_WORK_GROUP_SIZE:
+            if (context->getClientVersion() < Version(3, 1))
+            {
+                ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
+                return false;
+            }
+
+            // [OpenGL ES 3.1] Chapter 7.12 Page 122
+            // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
+            // program which has not been linked successfully, or which does not contain objects to
+            // form a compute shader.
+            if (!programObject->isLinked())
+            {
+                ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
+                return false;
+            }
+            if (!programObject->hasLinkedComputeShader())
+            {
+                ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
+                return false;
+            }
+            break;
+
         default:
             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
             return false;
diff --git a/src/tests/deqp_support/deqp_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_test_expectations.txt
index e231851..a868dc4 100644
--- a/src/tests/deqp_support/deqp_gles31_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles31_test_expectations.txt
@@ -1654,7 +1654,6 @@
 2324 DEBUG RELEASE : dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.program_not_active = FAIL
 2324 DEBUG RELEASE : dEQP-GLES31.functional.debug.negative_coverage.log.compute.program_not_active = FAIL
 2324 DEBUG RELEASE : dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.program_not_active = FAIL
-2324 DEBUG RELEASE : dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.invalid_program_query = FAIL
 2324 DEBUG RELEASE : dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_storage.block_number_limits = FAIL
 2324 DEBUG RELEASE : dEQP-GLES31.functional.debug.negative_coverage.log.shader_storage.block_number_limits = FAIL
 2324 DEBUG RELEASE : dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_storage.block_number_limits = FAIL
diff --git a/src/tests/gl_tests/ComputeShaderTest.cpp b/src/tests/gl_tests/ComputeShaderTest.cpp
index 5832a3e..d86fff1 100644
--- a/src/tests/gl_tests/ComputeShaderTest.cpp
+++ b/src/tests/gl_tests/ComputeShaderTest.cpp
@@ -1152,6 +1152,47 @@
     }
 }
 
+// Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
+// program which has not been linked successfully or which does not contain objects to form a
+// compute shader.
+TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)
+{
+    const std::string vsSource =
+        R"(#version 310 es
+        void main()
+        {
+        })";
+
+    const std::string fsSource =
+        R"(#version 310 es
+        void main()
+        {
+        })";
+
+    GLint workGroupSize[3];
+
+    ANGLE_GL_PROGRAM(graphicsProgram, vsSource, fsSource);
+    glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    GLuint computeProgram = glCreateProgram();
+    GLShader computeShader(GL_COMPUTE_SHADER);
+    glAttachShader(computeProgram, computeShader);
+    glLinkProgram(computeProgram);
+    glDetachShader(computeProgram, computeShader);
+
+    GLint linkStatus;
+    glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);
+    ASSERT_GL_FALSE(linkStatus);
+
+    glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+    glDeleteProgram(computeProgram);
+
+    ASSERT_GL_NO_ERROR();
+}
+
 // Check that it is not possible to create a compute shader when the context does not support ES
 // 3.10
 TEST_P(ComputeShaderTestES3, NotSupported)
diff --git a/src/tests/test_utils/gl_raii.h b/src/tests/test_utils/gl_raii.h
index c6af624..ab987d0 100644
--- a/src/tests/test_utils/gl_raii.h
+++ b/src/tests/test_utils/gl_raii.h
@@ -75,6 +75,22 @@
 using GLProgramPipeline   = GLWrapper<glGenProgramPipelines, glDeleteProgramPipelines>;
 using GLQueryEXT          = GLWrapper<glGenQueriesEXT, glDeleteQueriesEXT>;
 
+class GLShader : angle::NonCopyable
+{
+  public:
+    GLShader() = delete;
+    explicit GLShader(GLenum shaderType) { mHandle = glCreateShader(shaderType); }
+
+    ~GLShader() { glDeleteShader(mHandle); }
+
+    GLuint get() { return mHandle; }
+
+    operator GLuint() { return get(); }
+
+  private:
+    GLuint mHandle;
+};
+
 // Don't use GLProgram directly, use ANGLE_GL_PROGRAM.
 namespace priv
 {