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/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 51a4145..0e92f9d 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -86,6 +86,19 @@
     }
 }
 
+ShaderVariable *FindVariableInInterfaceBlock(const TString &name,
+                                             const TInterfaceBlock *interfaceBlock,
+                                             std::vector<InterfaceBlock> *infoList)
+{
+    ASSERT(interfaceBlock);
+    InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
+    ASSERT(namedBlock);
+
+    // Set static use on the parent interface block here
+    namedBlock->staticUse = true;
+    return FindVariable(name, &namedBlock->fields);
+}
+
 // Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
 // and interface blocks.
 class CollectVariablesTraverser : public TIntermTraverser
@@ -403,13 +416,7 @@
                 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
                 if (interfaceBlock)
                 {
-                    InterfaceBlock *namedBlock =
-                        FindVariable(interfaceBlock->name(), mUniformBlocks);
-                    ASSERT(namedBlock);
-                    var = FindVariable(symbolName, &namedBlock->fields);
-
-                    // Set static use on the parent interface block here
-                    namedBlock->staticUse = true;
+                    var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
                 }
                 else
                 {
@@ -420,6 +427,13 @@
                 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
             }
             break;
+            case EvqBuffer:
+            {
+                const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
+                var =
+                    FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
+            }
+            break;
             case EvqFragCoord:
                 recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings);
                 return;
@@ -663,6 +677,7 @@
         setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
         fieldVariable.isRowMajorLayout =
             (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
+        fieldVariable.isUnsizedArray = fieldType.isUnsizedArray();
         interfaceBlock->fields.push_back(fieldVariable);
     }
 }