Vulkan: Translate line loop indices from buffer.

When a line loop is drawn with byte indices from a buffer, translate
to short.  Enable test.

BUG=angleproject:2802

Change-Id: Ie178ec866387be85b91291c28e1978db0a09c20a
Reviewed-on: https://chromium-review.googlesource.com/1237293
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
Commit-Queue: Frank Henigman <fjhenigman@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index 30a1665..1e1f07e 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -479,13 +479,13 @@
         if (mDirtyLineLoopTranslation)
         {
             gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
-            VkIndexType indexType          = gl_vk::GetIndexType(drawCallParams.type());
 
             if (!elementArrayBuffer)
             {
-                ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
-                    contextVk, drawCallParams, &mCurrentElementArrayBufferHandle,
-                    &mCurrentElementArrayBufferOffset));
+                ANGLE_TRY(mLineLoopHelper.streamIndices(
+                    contextVk, drawCallParams.type(), drawCallParams.indexCount(),
+                    reinterpret_cast<const uint8_t *>(drawCallParams.indices()),
+                    &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
             }
             else
             {
@@ -493,8 +493,9 @@
                 intptr_t offset = reinterpret_cast<intptr_t>(drawCallParams.indices());
                 BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
                 ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
-                    contextVk, elementArrayBufferVk, indexType, drawCallParams.indexCount(), offset,
-                    &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
+                    contextVk, elementArrayBufferVk, drawCallParams.type(),
+                    drawCallParams.indexCount(), offset, &mCurrentElementArrayBufferHandle,
+                    &mCurrentElementArrayBufferOffset));
             }
         }
 
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
index 0de56f7..bb607f4 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -370,7 +370,7 @@
 
 LineLoopHelper::~LineLoopHelper() = default;
 
-angle::Result LineLoopHelper::getIndexBufferForDrawArrays(Context *context,
+angle::Result LineLoopHelper::getIndexBufferForDrawArrays(ContextVk *context,
                                                           const gl::DrawCallParams &drawCallParams,
                                                           VkBuffer *bufferHandleOut,
                                                           VkDeviceSize *offsetOut)
@@ -402,16 +402,30 @@
     return angle::Result::Continue();
 }
 
-angle::Result LineLoopHelper::getIndexBufferForElementArrayBuffer(Context *context,
+angle::Result LineLoopHelper::getIndexBufferForElementArrayBuffer(ContextVk *context,
                                                                   BufferVk *elementArrayBufferVk,
-                                                                  VkIndexType indexType,
+                                                                  GLenum glIndexType,
                                                                   int indexCount,
                                                                   intptr_t elementArrayOffset,
                                                                   VkBuffer *bufferHandleOut,
                                                                   VkDeviceSize *bufferOffsetOut)
 {
-    ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
+    if (glIndexType == GL_UNSIGNED_BYTE)
+    {
+        // Needed before reading buffer or we could get stale data.
+        ANGLE_TRY(context->getRenderer()->finish(context));
 
+        void *srcDataMapping = nullptr;
+        ANGLE_TRY(elementArrayBufferVk->mapImpl(context, &srcDataMapping));
+        ANGLE_TRY(streamIndices(context, glIndexType, indexCount,
+                                static_cast<const uint8_t *>(srcDataMapping) + elementArrayOffset,
+                                bufferHandleOut, bufferOffsetOut));
+        ANGLE_TRY(elementArrayBufferVk->unmapImpl(context));
+        return angle::Result::Continue();
+    }
+
+    VkIndexType indexType = gl_vk::GetIndexType(glIndexType);
+    ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
     uint32_t *indices          = nullptr;
 
     auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
@@ -439,40 +453,39 @@
     return angle::Result::Continue();
 }
 
-angle::Result LineLoopHelper::getIndexBufferForClientElementArray(
-    Context *context,
-    const gl::DrawCallParams &drawCallParams,
-    VkBuffer *bufferHandleOut,
-    VkDeviceSize *bufferOffsetOut)
+angle::Result LineLoopHelper::streamIndices(ContextVk *context,
+                                            GLenum glIndexType,
+                                            GLsizei indexCount,
+                                            const uint8_t *srcPtr,
+                                            VkBuffer *bufferHandleOut,
+                                            VkDeviceSize *bufferOffsetOut)
 {
-    VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
+    VkIndexType indexType = gl_vk::GetIndexType(glIndexType);
 
     uint8_t *indices = nullptr;
 
     auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
-    size_t allocateBytes = unitSize * (drawCallParams.indexCount() + 1);
+    size_t allocateBytes = unitSize * (indexCount + 1);
     ANGLE_TRY(mDynamicIndexBuffer.allocate(context, allocateBytes,
                                            reinterpret_cast<uint8_t **>(&indices), bufferHandleOut,
                                            bufferOffsetOut, nullptr));
 
-    if (drawCallParams.type() == GL_UNSIGNED_BYTE)
+    if (glIndexType == GL_UNSIGNED_BYTE)
     {
         // Vulkan doesn't support uint8 index types, so we need to emulate it.
         ASSERT(indexType == VK_INDEX_TYPE_UINT16);
         uint16_t *indicesDst  = reinterpret_cast<uint16_t *>(indices);
-        const uint8_t *srcPtr = reinterpret_cast<const uint8_t *>(drawCallParams.indices());
-        for (int i = 0; i < drawCallParams.indexCount(); i++)
+        for (int i = 0; i < indexCount; i++)
         {
             indicesDst[i] = srcPtr[i];
         }
 
-        indicesDst[drawCallParams.indexCount()] = srcPtr[0];
+        indicesDst[indexCount] = srcPtr[0];
     }
     else
     {
-        memcpy(indices, drawCallParams.indices(), unitSize * drawCallParams.indexCount());
-        memcpy(indices + unitSize * drawCallParams.indexCount(), drawCallParams.indices(),
-               unitSize);
+        memcpy(indices, srcPtr, unitSize * indexCount);
+        memcpy(indices + unitSize * indexCount, srcPtr, unitSize);
     }
 
     ANGLE_TRY(mDynamicIndexBuffer.flush(context));
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h
index 236a91b..b4b5879 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.h
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -138,21 +138,25 @@
     LineLoopHelper(RendererVk *renderer);
     ~LineLoopHelper();
 
-    angle::Result getIndexBufferForDrawArrays(Context *context,
+    angle::Result getIndexBufferForDrawArrays(ContextVk *context,
                                               const gl::DrawCallParams &drawCallParams,
                                               VkBuffer *bufferHandleOut,
                                               VkDeviceSize *offsetOut);
-    angle::Result getIndexBufferForElementArrayBuffer(Context *context,
+
+    angle::Result getIndexBufferForElementArrayBuffer(ContextVk *context,
                                                       BufferVk *elementArrayBufferVk,
-                                                      VkIndexType indexType,
+                                                      GLenum glIndexType,
                                                       int indexCount,
                                                       intptr_t elementArrayOffset,
                                                       VkBuffer *bufferHandleOut,
                                                       VkDeviceSize *bufferOffsetOut);
-    angle::Result getIndexBufferForClientElementArray(Context *context,
-                                                      const gl::DrawCallParams &drawCallParams,
-                                                      VkBuffer *bufferHandleOut,
-                                                      VkDeviceSize *bufferOffsetOut);
+
+    angle::Result streamIndices(ContextVk *context,
+                                GLenum glIndexType,
+                                GLsizei indexCount,
+                                const uint8_t *srcPtr,
+                                VkBuffer *bufferHandleOut,
+                                VkDeviceSize *bufferOffsetOut);
 
     void destroy(VkDevice device);
 
diff --git a/src/tests/gl_tests/LineLoopTest.cpp b/src/tests/gl_tests/LineLoopTest.cpp
index b290b86..7a362d0 100644
--- a/src/tests/gl_tests/LineLoopTest.cpp
+++ b/src/tests/gl_tests/LineLoopTest.cpp
@@ -132,9 +132,6 @@
 
 TEST_P(LineLoopTest, LineLoopUByteIndexBuffer)
 {
-    // TODO(jmadill): Diagnose and fix. http://anglebug.com/2802
-    ANGLE_SKIP_TEST_IF(IsVulkan());
-
     // Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
     ignoreD3D11SDKLayersWarnings();