ES31: Add BUFFER_VARIABLE and SHADER_STORAGE_BLOCK program interfaces

This patch collects the shader storage block members information.
It implements getShaderStorageBlockMemberInfo and getShaderStorageBlockSize
for OpenGL backend. Meanwhile, it implements BUFFER_VARIABLE and SHADER_STORAGE_BLOCK
interfaces for program query.

BUG=angleproject:1920
TEST=angle_end2end_tests:ProgramInterfaceTest*
     dEQP-GLES31.functional.layout_binding.ssbo*
     dEQP-GLES31.functional.compute.basic.empty
     dEQP-GLES31.functional.compute.basic.ssbo_rw*
     dEQP-GLES31.functional.compute.basic.ssbo_local_barrier*
     dEQP-GLES31.functional.compute.basic.copy_image_to_ssbo_small
     dEQP-GLES31.functional.compute.basic.copy_ssbo_multiple_groups
     dEQP-GLES31.functional.compute.basic.copy_ssbo_multiple_invocations
     dEQP-GLES31.functional.compute.basic.copy_ssbo_single_invocation
     dEQP-GLES31.functional.compute.basic.copy_ssbo_to_image_small
     dEQP-GLES31.functional.compute.basic.shared_var*
     dEQP-GLES31.functional.compute.basic.ubo_to_ssbo*
     dEQP-GLES31.functional.compute.basic.write_multiple_arr*
     dEQP-GLES31.functional.compute.shared_var.basic_type.*
     dEQP-GLES31.functional.compute.shared_var.work_group_size.*
     dEQP-GLES31.functional.atomic_counter.*

Change-Id: Ie8b81fde5a2e919aab77adb3d137c9ff2f193409
Reviewed-on: https://chromium-review.googlesource.com/712235
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp
index 466f1fa..a947636 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -580,6 +580,60 @@
     return true;
 }
 
+bool ProgramGL::getShaderStorageBlockMemberInfo(const std::string & /* memberName */,
+                                                const std::string &memberUniformMappedName,
+                                                sh::BlockMemberInfo *memberInfoOut) const
+{
+    const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
+    GLuint index =
+        mFunctions->getProgramResourceIndex(mProgramID, GL_BUFFER_VARIABLE, memberNameGLStr);
+
+    if (index == GL_INVALID_INDEX)
+    {
+        *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+        return false;
+    }
+
+    constexpr int kPropCount             = 5;
+    std::array<GLenum, kPropCount> props = {
+        {GL_ARRAY_STRIDE, GL_IS_ROW_MAJOR, GL_MATRIX_STRIDE, GL_OFFSET, GL_TOP_LEVEL_ARRAY_STRIDE}};
+    std::array<GLint, kPropCount> params;
+    GLsizei length;
+    mFunctions->getProgramResourceiv(mProgramID, GL_BUFFER_VARIABLE, index, kPropCount,
+                                     props.data(), kPropCount, &length, params.data());
+    ASSERT(kPropCount == length);
+    memberInfoOut->arrayStride         = params[0];
+    memberInfoOut->isRowMajorMatrix    = params[1];
+    memberInfoOut->matrixStride        = params[2];
+    memberInfoOut->offset              = params[3];
+    memberInfoOut->topLevelArrayStride = params[4];
+
+    return true;
+}
+
+bool ProgramGL::getShaderStorageBlockSize(const std::string &name,
+                                          const std::string &mappedName,
+                                          size_t *sizeOut) const
+{
+    const GLchar *nameGLStr = mappedName.c_str();
+    GLuint index =
+        mFunctions->getProgramResourceIndex(mProgramID, GL_SHADER_STORAGE_BLOCK, nameGLStr);
+
+    if (index == GL_INVALID_INDEX)
+    {
+        *sizeOut = 0;
+        return false;
+    }
+
+    GLenum prop    = GL_BUFFER_DATA_SIZE;
+    GLsizei length = 0;
+    GLint dataSize = 0;
+    mFunctions->getProgramResourceiv(mProgramID, GL_SHADER_STORAGE_BLOCK, index, 1, &prop, 1,
+                                     &length, &dataSize);
+    *sizeOut = static_cast<size_t>(dataSize);
+    return true;
+}
+
 void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
                                         GLenum genMode,
                                         GLint components,
@@ -822,18 +876,16 @@
 
     resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
 
-    // TODO(jiajia.qin@intel.com): Determine correct shader storage block info.
-    auto getShaderStorageBlockSize = [](const std::string &name, const std::string &mappedName,
-                                        size_t *sizeOut) {
-        *sizeOut = 0;
-        return true;
+    auto getShaderStorageBlockSize = [this](const std::string &name, const std::string &mappedName,
+                                            size_t *sizeOut) {
+        return this->getShaderStorageBlockSize(name, mappedName, sizeOut);
     };
 
-    auto getShaderStorageBlockMemberInfo =
-        [](const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut) {
-            *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
-            return true;
-        };
+    auto getShaderStorageBlockMemberInfo = [this](const std::string &name,
+                                                  const std::string &mappedName,
+                                                  sh::BlockMemberInfo *infoOut) {
+        return this->getShaderStorageBlockMemberInfo(name, mappedName, infoOut);
+    };
     resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
                                                   getShaderStorageBlockMemberInfo);
 }