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/MemoryProgramCache.cpp b/src/libANGLE/MemoryProgramCache.cpp
index 9add9f5..5fa6f64 100644
--- a/src/libANGLE/MemoryProgramCache.cpp
+++ b/src/libANGLE/MemoryProgramCache.cpp
@@ -90,6 +90,38 @@
     }
 }
 
+void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
+{
+    WriteShaderVar(stream, var);
+
+    stream->writeInt(var.bufferIndex);
+    stream->writeInt(var.blockInfo.offset);
+    stream->writeInt(var.blockInfo.arrayStride);
+    stream->writeInt(var.blockInfo.matrixStride);
+    stream->writeInt(var.blockInfo.isRowMajorMatrix);
+    stream->writeInt(var.blockInfo.topLevelArrayStride);
+    stream->writeInt(var.topLevelArraySize);
+    stream->writeInt(var.vertexStaticUse);
+    stream->writeInt(var.fragmentStaticUse);
+    stream->writeInt(var.computeStaticUse);
+}
+
+void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
+{
+    LoadShaderVar(stream, var);
+
+    var->bufferIndex                   = stream->readInt<int>();
+    var->blockInfo.offset              = stream->readInt<int>();
+    var->blockInfo.arrayStride         = stream->readInt<int>();
+    var->blockInfo.matrixStride        = stream->readInt<int>();
+    var->blockInfo.isRowMajorMatrix    = stream->readBool();
+    var->blockInfo.topLevelArrayStride = stream->readInt<int>();
+    var->topLevelArraySize             = stream->readInt<int>();
+    var->vertexStaticUse               = stream->readBool();
+    var->fragmentStaticUse             = stream->readBool();
+    var->computeStaticUse              = stream->readBool();
+}
+
 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
 {
     stream->writeString(block.name);
@@ -257,6 +289,15 @@
         state->mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
     }
 
+    unsigned int bufferVariableCount = stream.readInt<unsigned int>();
+    ASSERT(state->mBufferVariables.empty());
+    for (unsigned int index = 0; index < bufferVariableCount; ++index)
+    {
+        BufferVariable bufferVariable;
+        LoadBufferVariable(&stream, &bufferVariable);
+        state->mBufferVariables.push_back(bufferVariable);
+    }
+
     unsigned int shaderStorageBlockCount = stream.readInt<unsigned int>();
     ASSERT(state->mShaderStorageBlocks.empty());
     for (unsigned int shaderStorageBlockIndex = 0;
@@ -438,6 +479,12 @@
         WriteInterfaceBlock(&stream, uniformBlock);
     }
 
+    stream.writeInt(state.getBufferVariables().size());
+    for (const BufferVariable &bufferVariable : state.getBufferVariables())
+    {
+        WriteBufferVariable(&stream, bufferVariable);
+    }
+
     stream.writeInt(state.getShaderStorageBlocks().size());
     for (const InterfaceBlock &shaderStorageBlock : state.getShaderStorageBlocks())
     {