Vulkan: Support for uniform arrays

- Enable dEQP tests for uniform arrays
- Fix the shader translator to support arrays
- Fix for finding the uniforms location
- Support get/set of uniform array values

Bug: angleproject:2416

Change-Id: I7d0e9c602840ffb915f8ea3ba5d832d03bd74985
Reviewed-on: https://chromium-review.googlesource.com/984599
Commit-Queue: Luc Ferron <lucferron@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index ad577b0..9de8fad 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -58,40 +58,59 @@
 
 template <typename T>
 void UpdateDefaultUniformBlock(GLsizei count,
+                               uint32_t arrayIndex,
                                int componentCount,
                                const T *v,
                                const sh::BlockMemberInfo &layoutInfo,
                                angle::MemoryBuffer *uniformData)
 {
-    int elementSize = sizeof(T) * componentCount;
+    const int elementSize = sizeof(T) * componentCount;
+
+    uint8_t *dst = uniformData->data() + layoutInfo.offset;
     if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
     {
-        uint8_t *writePtr = uniformData->data() + layoutInfo.offset;
+        uint32_t arrayOffset = arrayIndex * layoutInfo.arrayStride;
+        uint8_t *writePtr    = dst + arrayOffset;
         memcpy(writePtr, v, elementSize * count);
     }
     else
     {
-        UNIMPLEMENTED();
+        // Have to respect the arrayStride between each element of the array.
+        int maxIndex = arrayIndex + count;
+        for (int writeIndex = arrayIndex, readIndex = 0; writeIndex < maxIndex;
+             writeIndex++, readIndex++)
+        {
+            const int arrayOffset = writeIndex * layoutInfo.arrayStride;
+            uint8_t *writePtr     = dst + arrayOffset;
+            const T *readPtr      = v + readIndex;
+            memcpy(writePtr, readPtr, elementSize);
+        }
     }
 }
 
 template <typename T>
 void ReadFromDefaultUniformBlock(int componentCount,
+                                 uint32_t arrayIndex,
                                  T *dst,
                                  const sh::BlockMemberInfo &layoutInfo,
                                  const angle::MemoryBuffer *uniformData)
 {
     ASSERT(layoutInfo.offset != -1);
 
-    int elementSize = sizeof(T) * componentCount;
+    const int elementSize = sizeof(T) * componentCount;
+    const uint8_t *source = uniformData->data() + layoutInfo.offset;
+
     if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
     {
-        const uint8_t *readPtr = uniformData->data() + layoutInfo.offset;
+        const uint8_t *readPtr = source + arrayIndex * layoutInfo.arrayStride;
         memcpy(dst, readPtr, elementSize);
     }
     else
     {
-        UNIMPLEMENTED();
+        // Have to respect the arrayStride between each element of the array.
+        const int arrayOffset  = arrayIndex * layoutInfo.arrayStride;
+        const uint8_t *readPtr = source + arrayOffset;
+        memcpy(dst, readPtr, elementSize);
     }
 }
 
@@ -314,7 +333,8 @@
             std::string uniformName = uniform.name;
             if (uniform.isArray())
             {
-                uniformName += ArrayString(location.arrayIndex);
+                // Gets the uniform name without the [0] at the end.
+                uniformName = gl::ParseResourceName(uniformName, nullptr);
             }
 
             bool found = false;
@@ -429,7 +449,8 @@
                 continue;
             }
 
-            UpdateDefaultUniformBlock(count, linkedUniform.typeInfo->componentCount, v, layoutInfo,
+            UpdateDefaultUniformBlock(count, locationInfo.arrayIndex,
+                                      linkedUniform.typeInfo->componentCount, v, layoutInfo,
                                       &uniformBlock.uniformData);
 
             uniformBlock.uniformsDirty = true;
@@ -461,8 +482,8 @@
     const DefaultUniformBlock &uniformBlock =
         mDefaultUniformBlocks[static_cast<GLuint>(shaderType)];
     const sh::BlockMemberInfo &layoutInfo   = uniformBlock.uniformLayout[location];
-    ReadFromDefaultUniformBlock(linkedUniform.typeInfo->componentCount, v, layoutInfo,
-                                &uniformBlock.uniformData);
+    ReadFromDefaultUniformBlock(linkedUniform.typeInfo->componentCount, locationInfo.arrayIndex, v,
+                                layoutInfo, &uniformBlock.uniformData);
 }
 
 void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)