ES31: Add atomic counter buffer data size

BUG=angleproject:1729
TEST=dEQP-GLES31.functional.ssbo.layout.*
     dEQP-GLES31.functional.compute.basic.atomic_counter*

Change-Id: Ic78c0f089fd539c0b1064e8405d63505456dbc01
Reviewed-on: https://chromium-review.googlesource.com/777958
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 7364f80..86a1622 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -854,7 +854,8 @@
         ProgramLinkedResources resources = {
             {0, PackMode::ANGLE_RELAXED},
             {&mState.mUniformBlocks, &mState.mUniforms},
-            {&mState.mShaderStorageBlocks, &mState.mBufferVariables}};
+            {&mState.mShaderStorageBlocks, &mState.mBufferVariables},
+            {&mState.mAtomicCounterBuffers}};
 
         InitUniformBlockLinker(context, mState, &resources.uniformBlockLinker);
         InitShaderStorageBlockLinker(context, mState, &resources.shaderStorageBlockLinker);
@@ -924,7 +925,8 @@
         ProgramLinkedResources resources = {
             {data.getCaps().maxVaryingVectors, packMode},
             {&mState.mUniformBlocks, &mState.mUniforms},
-            {&mState.mShaderStorageBlocks, &mState.mBufferVariables}};
+            {&mState.mShaderStorageBlocks, &mState.mBufferVariables},
+            {&mState.mAtomicCounterBuffers}};
 
         InitUniformBlockLinker(context, mState, &resources.uniformBlockLinker);
         InitShaderStorageBlockLinker(context, mState, &resources.shaderStorageBlockLinker);
@@ -949,7 +951,6 @@
         gatherTransformFeedbackVaryings(mergedVaryings);
     }
 
-    gatherAtomicCounterBuffers();
     initInterfaceBlockBindings();
 
     setUniformValuesFromBindingQualifiers();
@@ -2140,6 +2141,11 @@
     for (unsigned int index : mState.mAtomicCounterUniformRange)
     {
         auto &uniform = mState.mUniforms[index];
+        uniform.blockInfo.offset           = uniform.offset;
+        uniform.blockInfo.arrayStride      = (uniform.isArray() ? 4 : 0);
+        uniform.blockInfo.matrixStride     = 0;
+        uniform.blockInfo.isRowMajorMatrix = false;
+
         bool found    = false;
         for (unsigned int bufferIndex = 0; bufferIndex < mState.mAtomicCounterBuffers.size();
              ++bufferIndex)
@@ -2911,20 +2917,6 @@
     }
 }
 
-void Program::gatherAtomicCounterBuffers()
-{
-    for (unsigned int index : mState.mAtomicCounterUniformRange)
-    {
-        auto &uniform                      = mState.mUniforms[index];
-        uniform.blockInfo.offset           = uniform.offset;
-        uniform.blockInfo.arrayStride      = (uniform.isArray() ? 4 : 0);
-        uniform.blockInfo.matrixStride     = 0;
-        uniform.blockInfo.isRowMajorMatrix = false;
-    }
-
-    // TODO(jie.a.chen@intel.com): Get the actual BUFFER_DATA_SIZE from backend for each buffer.
-}
-
 void Program::initInterfaceBlockBindings()
 {
     // Set initial bindings from shader.
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index 61fbce1..ef02b10 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -673,7 +673,6 @@
 
     void setUniformValuesFromBindingQualifiers();
 
-    void gatherAtomicCounterBuffers();
     void initInterfaceBlockBindings();
 
     // Both these function update the cached uniform values and return a modified "count"
diff --git a/src/libANGLE/ProgramLinkedResources.cpp b/src/libANGLE/ProgramLinkedResources.cpp
index d4308a3..bcd2e05 100644
--- a/src/libANGLE/ProgramLinkedResources.cpp
+++ b/src/libANGLE/ProgramLinkedResources.cpp
@@ -1036,4 +1036,25 @@
     return mBufferVariablesOut->size();
 }
 
+// AtomicCounterBufferLinker implementation.
+AtomicCounterBufferLinker::AtomicCounterBufferLinker(
+    std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut)
+    : mAtomicCounterBuffersOut(atomicCounterBuffersOut)
+{
+}
+
+AtomicCounterBufferLinker::~AtomicCounterBufferLinker()
+{
+}
+
+void AtomicCounterBufferLinker::link(const std::map<int, unsigned int> &sizeMap) const
+{
+    for (auto &atomicCounterBuffer : *mAtomicCounterBuffersOut)
+    {
+        auto bufferSize = sizeMap.find(atomicCounterBuffer.binding);
+        ASSERT(bufferSize != sizeMap.end());
+        atomicCounterBuffer.dataSize = bufferSize->second;
+    }
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/ProgramLinkedResources.h b/src/libANGLE/ProgramLinkedResources.h
index 8ee374f..891ebe7 100644
--- a/src/libANGLE/ProgramLinkedResources.h
+++ b/src/libANGLE/ProgramLinkedResources.h
@@ -37,6 +37,9 @@
 class ProgramBindings;
 class Shader;
 struct VariableLocation;
+struct ShaderVariableBuffer;
+
+using AtomicCounterBuffer = ShaderVariableBuffer;
 
 class UniformLinker final : angle::NonCopyable
 {
@@ -277,6 +280,18 @@
     std::vector<BufferVariable> *mBufferVariablesOut;
 };
 
+class AtomicCounterBufferLinker final : angle::NonCopyable
+{
+  public:
+    AtomicCounterBufferLinker(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut);
+    ~AtomicCounterBufferLinker();
+
+    void link(const std::map<int, unsigned int> &sizeMap) const;
+
+  private:
+    std::vector<AtomicCounterBuffer> *mAtomicCounterBuffersOut;
+};
+
 // The link operation is responsible for finishing the link of uniform and interface blocks.
 // This way it can filter out unreferenced resources and still have access to the info.
 // TODO(jmadill): Integrate uniform linking/filtering as well as interface blocks.
@@ -285,6 +300,7 @@
     VaryingPacking varyingPacking;
     UniformBlockLinker uniformBlockLinker;
     ShaderStorageBlockLinker shaderStorageBlockLinker;
+    AtomicCounterBufferLinker atomicCounterBufferLinker;
 };
 
 }  // namespace gl
diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp
index 16455de..fc4aebb 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -635,6 +635,32 @@
     return true;
 }
 
+void ProgramGL::getAtomicCounterBufferSizeMap(std::map<int, unsigned int> *sizeMapOut) const
+{
+    if (mFunctions->getProgramInterfaceiv == nullptr)
+    {
+        return;
+    }
+
+    int resourceCount = 0;
+    mFunctions->getProgramInterfaceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES,
+                                      &resourceCount);
+
+    for (int index = 0; index < resourceCount; index++)
+    {
+        constexpr int kPropCount             = 2;
+        std::array<GLenum, kPropCount> props = {{GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE}};
+        std::array<GLint, kPropCount> params;
+        GLsizei length;
+        mFunctions->getProgramResourceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, index, kPropCount,
+                                         props.data(), kPropCount, &length, params.data());
+        ASSERT(kPropCount == length);
+        int bufferBinding           = params[0];
+        unsigned int bufferDataSize = params[1];
+        sizeMapOut->insert(std::pair<int, unsigned int>(bufferBinding, bufferDataSize));
+    }
+}
+
 void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
                                         GLenum genMode,
                                         GLint components,
@@ -889,6 +915,11 @@
     };
     resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
                                                   getShaderStorageBlockMemberInfo);
+
+    // Gather atomic counter buffer info.
+    std::map<int, unsigned int> sizeMap;
+    getAtomicCounterBufferSizeMap(&sizeMap);
+    resources.atomicCounterBufferLinker.link(sizeMap);
 }
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/gl/ProgramGL.h b/src/libANGLE/renderer/gl/ProgramGL.h
index ccff28b..e79a6a4 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.h
+++ b/src/libANGLE/renderer/gl/ProgramGL.h
@@ -102,6 +102,8 @@
     bool getShaderStorageBlockSize(const std::string &blockName,
                                    const std::string &blockMappedName,
                                    size_t *sizeOut) const;
+    void getAtomicCounterBufferSizeMap(std::map<int, unsigned int> *sizeMapOut) const;
+
     void linkResources(const gl::ProgramLinkedResources &resources);
 
     // Helper function, makes it simpler to type.
diff --git a/src/tests/deqp_support/deqp_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_test_expectations.txt
index c88d071..a8df744 100644
--- a/src/tests/deqp_support/deqp_gles31_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles31_test_expectations.txt
@@ -65,6 +65,7 @@
 1442 D3D11 : dEQP-GLES31.functional.state_query.internal_format.renderbuffer.* = FAIL
 1442 D3D11 : dEQP-GLES31.functional.state_query.program.compute_work_group_size_get_programiv = FAIL
 1442 D3D11 : dEQP-GLES31.functional.layout_binding.ssbo.* = FAIL
+1442 D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter* = FAIL
 1442 D3D11 : dEQP-GLES31.functional.compute.basic.empty = FAIL
 1442 D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_local_barrier_single_invocation = FAIL
 1442 D3D11 : dEQP-GLES31.functional.compute.basic.ssbo_local_barrier_single_group = FAIL
@@ -544,7 +545,50 @@
 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform_block.resource_list.block_array = FAIL
 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform_block.resource_list.block_array_single_element = FAIL
 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform_block.referenced_by.* = FAIL
-1951 OPENGL : dEQP-GLES31.functional.ssbo.layout.* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.2_level_unsized* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct.per_block_buffer.shared_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct.per_block_buffer.packed_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct.per_block_buffer.std140_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct.per_block_buffer.std430_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct.single_buffer.* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct_array.single_buffer.* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct.single_buffer.* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct_array.per_block_buffer.shared_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct_array.per_block_buffer.packed_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct_array.per_block_buffer.std140_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_struct_array.per_block_buffer.std430_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct.per_block_buffer.shared_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct.per_block_buffer.packed_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct.per_block_buffer.std140_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct.per_block_buffer.std430_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.single_buffer.* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.per_block_buffer.shared_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.per_block_buffer.packed_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.per_block_buffer.std140_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.per_block_buffer.std430_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.unsized* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.instance* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_basic_types.per_block_buffer.shared_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_basic_types.per_block_buffer.packed_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_basic_types.per_block_buffer.std140_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_basic_types.per_block_buffer.std430_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_basic_types.single_buffer.shared_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_basic_types.single_buffer.packed_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_basic_types.single_buffer.std140_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_basic_types.single_buffer.std430_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_nested_struct.per_block_buffer.shared_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_nested_struct.per_block_buffer.packed_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_nested_struct.per_block_buffer.std140_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_nested_struct.per_block_buffer.std430_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_nested_struct.single_buffer.shared_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_nested_struct.single_buffer.packed_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_nested_struct.single_buffer.std140_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.multi_nested_struct.single_buffer.std430_instance_array = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.random.basic_instance_arrays* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.random.nested_structs* = FAIL
+1729 OPENGL : dEQP-GLES31.functional.ssbo.layout.random.all* = FAIL
+2272 WIN NVIDIA OPENGL : dEQP-GLES31.functional.ssbo.layout.3_level_unsized* = FAIL
+2272 WIN NVIDIA OPENGL : dEQP-GLES31.functional.ssbo.layout.random.arrays_of_arrays* = FAIL
 
 // OpenGL and D3D11 Failing Tests
 1663 OPENGL D3D11 : dEQP-GLES31.functional.draw_indirect.compute_interop.* = FAIL
@@ -1199,10 +1243,6 @@
 1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.copy_ssbo_to_image_large = FAIL
 1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.image_barrier_single = FAIL
 1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.image_barrier_multiple = FAIL
-1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_single_invocation = FAIL
-1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_single_group = FAIL
-1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_multiple_invocations = FAIL
-1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.basic.atomic_counter_multiple_groups = FAIL
 1442 OPENGL D3D11 : dEQP-GLES31.functional.compute.indirect_dispatch.* = FAIL
 1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.basic_type_arrays.4 = FAIL
 1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.basic_type_arrays.10 = FAIL