ES31 program query: support AtomicCounterBuffer and UniformBlock

Calculates atomic counter buffer's shader reference according to its
child counters.
Merges GL_UNIFORM_BLOCK_* queries to GL_*.
Refreshes deqp_gles31_test_expectations.

BUG=angleproject:1920
TEST=angle_end2end_tests:ProgramInterfaceTest*
     dEQP-GLES31.functional.state_query.program.active_atomic_counter_buffers_get_programiv
     dEQP-GLES31.functional.layout_binding.ubo.*
Change-Id: Ia23ddfef5f5dd7e15628f4c259273e1c01c14d80
Reviewed-on: https://chromium-review.googlesource.com/715436
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/queryutils.cpp b/src/libANGLE/queryutils.cpp
index 29389ec..7270276 100644
--- a/src/libANGLE/queryutils.cpp
+++ b/src/libANGLE/queryutils.cpp
@@ -543,11 +543,13 @@
         case GL_UNIFORM_BLOCK:
             return clampCast<GLint>(program->getState().getUniformBlocks().size());
 
+        case GL_ATOMIC_COUNTER_BUFFER:
+            return clampCast<GLint>(program->getState().getAtomicCounterBuffers().size());
+
         // TODO(jie.a.chen@intel.com): more interfaces.
         case GL_TRANSFORM_FEEDBACK_VARYING:
         case GL_BUFFER_VARIABLE:
         case GL_SHADER_STORAGE_BLOCK:
-        case GL_ATOMIC_COUNTER_BUFFER:
             UNIMPLEMENTED();
             return 0;
 
@@ -613,10 +615,12 @@
         case GL_UNIFORM_BLOCK:
             return FindMaxSize(program->getState().getUniformBlocks(),
                                &InterfaceBlock::memberIndexes);
+        case GL_ATOMIC_COUNTER_BUFFER:
+            return FindMaxSize(program->getState().getAtomicCounterBuffers(),
+                               &AtomicCounterBuffer::memberIndexes);
 
         // TODO(jie.a.chen@intel.com): more interfaces.
         case GL_SHADER_STORAGE_BLOCK:
-        case GL_ATOMIC_COUNTER_BUFFER:
             UNIMPLEMENTED();
             return 0;
 
@@ -652,6 +656,117 @@
     }
 }
 
+GLenum GetUniformBlockPropertyEnum(GLenum prop)
+{
+    switch (prop)
+    {
+        case GL_UNIFORM_BLOCK_BINDING:
+            return GL_BUFFER_BINDING;
+
+        case GL_UNIFORM_BLOCK_DATA_SIZE:
+            return GL_BUFFER_DATA_SIZE;
+
+        case GL_UNIFORM_BLOCK_NAME_LENGTH:
+            return GL_NAME_LENGTH;
+
+        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+            return GL_NUM_ACTIVE_VARIABLES;
+
+        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+            return GL_ACTIVE_VARIABLES;
+
+        case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+            return GL_REFERENCED_BY_VERTEX_SHADER;
+
+        case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+            return GL_REFERENCED_BY_FRAGMENT_SHADER;
+
+        default:
+            return prop;
+    }
+}
+
+void GetShaderVariableBufferResourceProperty(const ShaderVariableBuffer &buffer,
+                                             GLenum pname,
+                                             GLint *params,
+                                             GLsizei bufSize,
+                                             GLsizei *outputPosition)
+
+{
+    switch (pname)
+    {
+        case GL_BUFFER_BINDING:
+            params[(*outputPosition)++] = buffer.binding;
+            break;
+        case GL_BUFFER_DATA_SIZE:
+            params[(*outputPosition)++] = clampCast<GLint>(buffer.dataSize);
+            break;
+        case GL_NUM_ACTIVE_VARIABLES:
+            params[(*outputPosition)++] = buffer.numActiveVariables();
+            break;
+        case GL_ACTIVE_VARIABLES:
+            for (size_t memberIndex = 0;
+                 memberIndex < buffer.memberIndexes.size() && *outputPosition < bufSize;
+                 ++memberIndex)
+            {
+                params[(*outputPosition)++] = clampCast<GLint>(buffer.memberIndexes[memberIndex]);
+            }
+            break;
+        case GL_REFERENCED_BY_VERTEX_SHADER:
+            params[(*outputPosition)++] = static_cast<GLint>(buffer.vertexStaticUse);
+            break;
+        case GL_REFERENCED_BY_FRAGMENT_SHADER:
+            params[(*outputPosition)++] = static_cast<GLint>(buffer.fragmentStaticUse);
+            break;
+        case GL_REFERENCED_BY_COMPUTE_SHADER:
+            params[(*outputPosition)++] = static_cast<GLint>(buffer.computeStaticUse);
+            break;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
+
+void GetInterfaceBlockResourceProperty(const InterfaceBlock &block,
+                                       GLenum pname,
+                                       GLint *params,
+                                       GLsizei bufSize,
+                                       GLsizei *outputPosition)
+{
+    if (pname == GL_NAME_LENGTH)
+    {
+        params[(*outputPosition)++] = clampCast<GLint>(block.nameWithArrayIndex().size() + 1);
+        return;
+    }
+    GetShaderVariableBufferResourceProperty(block, pname, params, bufSize, outputPosition);
+}
+
+void GetUniformBlockResourceProperty(const Program *program,
+                                     GLuint blockIndex,
+                                     GLenum pname,
+                                     GLint *params,
+                                     GLsizei bufSize,
+                                     GLsizei *outputPosition)
+
+{
+    ASSERT(*outputPosition < bufSize);
+    const auto &block = program->getUniformBlockByIndex(blockIndex);
+    GetInterfaceBlockResourceProperty(block, pname, params, bufSize, outputPosition);
+}
+
+void GetAtomicCounterBufferResourceProperty(const Program *program,
+                                            GLuint index,
+                                            GLenum pname,
+                                            GLint *params,
+                                            GLsizei bufSize,
+                                            GLsizei *outputPosition)
+
+{
+    ASSERT(*outputPosition < bufSize);
+    const auto &buffer = program->getState().getAtomicCounterBuffers()[index];
+    GetShaderVariableBufferResourceProperty(buffer, pname, params, bufSize, outputPosition);
+}
+
 }  // anonymous namespace
 
 void QueryFramebufferAttachmentParameteriv(const Framebuffer *framebuffer,
@@ -861,6 +976,9 @@
             params[2]                          = localSize[2];
         }
         break;
+        case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
+            *params = program->getActiveAtomicCounterBufferCount();
+            break;
         default:
             UNREACHABLE();
             break;
@@ -1044,39 +1162,9 @@
                                GLenum pname,
                                GLint *params)
 {
-    const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
-    switch (pname)
-    {
-        case GL_UNIFORM_BLOCK_BINDING:
-            *params = clampCast<GLint>(program->getUniformBlockBinding(uniformBlockIndex));
-            break;
-        case GL_UNIFORM_BLOCK_DATA_SIZE:
-            *params = clampCast<GLint>(uniformBlock.dataSize);
-            break;
-        case GL_UNIFORM_BLOCK_NAME_LENGTH:
-            *params = clampCast<GLint>(uniformBlock.nameWithArrayIndex().size() + 1);
-            break;
-        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
-            *params = clampCast<GLint>(uniformBlock.memberIndexes.size());
-            break;
-        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
-            for (size_t blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberIndexes.size();
-                 blockMemberIndex++)
-            {
-                params[blockMemberIndex] =
-                    clampCast<GLint>(uniformBlock.memberIndexes[blockMemberIndex]);
-            }
-            break;
-        case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
-            *params = static_cast<GLint>(uniformBlock.vertexStaticUse);
-            break;
-        case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
-            *params = static_cast<GLint>(uniformBlock.fragmentStaticUse);
-            break;
-        default:
-            UNREACHABLE();
-            break;
-    }
+    GLenum prop = GetUniformBlockPropertyEnum(pname);
+    QueryProgramResourceiv(program, GL_UNIFORM_BLOCK, uniformBlockIndex, 1, &prop,
+                           std::numeric_limits<GLsizei>::max(), nullptr, params);
 }
 
 void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params)
@@ -1317,8 +1405,10 @@
         case GL_UNIFORM:
             return program->getState().getUniformIndexFromName(name);
 
-        // TODO(jie.a.chen@intel.com): more interfaces.
         case GL_UNIFORM_BLOCK:
+            return program->getUniformBlockIndex(name);
+
+        // TODO(jie.a.chen@intel.com): more interfaces.
         case GL_TRANSFORM_FEEDBACK_VARYING:
         case GL_BUFFER_VARIABLE:
         case GL_SHADER_STORAGE_BLOCK:
@@ -1352,8 +1442,11 @@
             program->getUniformResourceName(index, bufSize, length, name);
             break;
 
-        // TODO(jie.a.chen@intel.com): more interfaces.
         case GL_UNIFORM_BLOCK:
+            program->getActiveUniformBlockName(index, bufSize, length, name);
+            break;
+
+        // TODO(jie.a.chen@intel.com): more interfaces.
         case GL_TRANSFORM_FEEDBACK_VARYING:
         case GL_BUFFER_VARIABLE:
         case GL_SHADER_STORAGE_BLOCK:
@@ -1380,14 +1473,6 @@
         case GL_UNIFORM:
             return program->getState().getUniformLocation(name);
 
-        // TODO(jie.a.chen@intel.com): more interfaces.
-        case GL_UNIFORM_BLOCK:
-        case GL_TRANSFORM_FEEDBACK_VARYING:
-        case GL_BUFFER_VARIABLE:
-        case GL_SHADER_STORAGE_BLOCK:
-            UNIMPLEMENTED();
-            return -1;
-
         default:
             UNREACHABLE();
             return -1;
@@ -1412,34 +1497,37 @@
         return;
     }
 
-    GLsizei count = std::min(propCount, bufSize);
-    if (length != nullptr)
-    {
-        *length = count;
-    }
-
-    for (GLsizei i = 0; i < count; i++)
+    GLsizei pos = 0;
+    for (GLsizei i = 0; i < propCount; i++)
     {
         switch (programInterface)
         {
             case GL_PROGRAM_INPUT:
                 params[i] = GetInputResourceProperty(program, index, props[i]);
+                ++pos;
                 break;
 
             case GL_PROGRAM_OUTPUT:
                 params[i] = GetOutputResourceProperty(program, index, props[i]);
+                ++pos;
                 break;
 
             case GL_UNIFORM:
                 params[i] = GetUniformResourceProperty(program, index, props[i]);
+                ++pos;
+                break;
+            case GL_UNIFORM_BLOCK:
+                GetUniformBlockResourceProperty(program, index, props[i], params, bufSize, &pos);
                 break;
 
+            case GL_ATOMIC_COUNTER_BUFFER:
+                GetAtomicCounterBufferResourceProperty(program, index, props[i], params, bufSize,
+                                                       &pos);
+                break;
             // TODO(jie.a.chen@intel.com): more interfaces.
-            case GL_UNIFORM_BLOCK:
             case GL_TRANSFORM_FEEDBACK_VARYING:
             case GL_BUFFER_VARIABLE:
             case GL_SHADER_STORAGE_BLOCK:
-            case GL_ATOMIC_COUNTER_BUFFER:
                 UNIMPLEMENTED();
                 params[i] = GL_INVALID_VALUE;
                 break;
@@ -1448,6 +1536,17 @@
                 UNREACHABLE();
                 params[i] = GL_INVALID_VALUE;
         }
+        if (pos == bufSize)
+        {
+            // Most properties return one value, but GL_ACTIVE_VARIABLES returns an array of values.
+            // This checks not to break buffer bounds for such case.
+            break;
+        }
+    }
+
+    if (length != nullptr)
+    {
+        *length = pos;
     }
 }