//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VertexArrayVk.cpp:
//    Implements the class methods for VertexArrayVk.
//

#include "libANGLE/renderer/vulkan/VertexArrayVk.h"

#include "common/debug.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include "third_party/trace_event/trace_event.h"

namespace rx
{
namespace
{
constexpr size_t kDynamicVertexDataSize    = 1024 * 1024;
constexpr size_t kDynamicIndexDataSize     = 1024 * 8;
constexpr size_t kMaxVertexFormatAlignment = 4;
constexpr VkBufferUsageFlags kVertexBufferUsageFlags =
    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
constexpr VkBufferUsageFlags kIndexBufferUsageFlags = VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
                                                      VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
                                                      VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;

ANGLE_INLINE bool BindingIsAligned(const gl::VertexBinding &binding,
                                   const angle::Format &angleFormat,
                                   unsigned int attribSize)
{
    GLuint mask = angleFormat.componentAlignmentMask;
    if (mask != std::numeric_limits<GLuint>::max())
    {
        return ((binding.getOffset() & mask) == 0 && (binding.getStride() & mask) == 0);
    }
    else
    {
        unsigned int formatSize = angleFormat.pixelBytes;
        return ((binding.getOffset() * attribSize) % formatSize == 0) &&
               ((binding.getStride() * attribSize) % formatSize == 0);
    }
}

angle::Result StreamVertexData(ContextVk *contextVk,
                               vk::DynamicBuffer *dynamicBuffer,
                               const uint8_t *sourceData,
                               size_t bytesToAllocate,
                               size_t destOffset,
                               size_t vertexCount,
                               size_t stride,
                               VertexCopyFunction vertexLoadFunction,
                               vk::BufferHelper **bufferOut,
                               VkDeviceSize *bufferOffsetOut)
{
    uint8_t *dst = nullptr;
    ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, nullptr, bufferOffsetOut,
                                      nullptr));
    *bufferOut = dynamicBuffer->getCurrentBuffer();
    dst += destOffset;
    vertexLoadFunction(sourceData, stride, vertexCount, dst);

    ANGLE_TRY(dynamicBuffer->flush(contextVk));
    return angle::Result::Continue;
}

size_t GetVertexCount(BufferVk *srcBuffer, const gl::VertexBinding &binding, uint32_t srcFormatSize)
{
    // Bytes usable for vertex data.
    GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
    if (bytes < srcFormatSize)
        return 0;

    // Count the last vertex.  It may occupy less than a full stride.
    size_t numVertices = 1;
    bytes -= srcFormatSize;

    // Count how many strides fit remaining space.
    if (bytes > 0)
        numVertices += static_cast<size_t>(bytes) / binding.getStride();

    return numVertices;
}
}  // anonymous namespace

#define INIT                                    \
    {                                           \
        kVertexBufferUsageFlags, 1024 * 8, true \
    }

VertexArrayVk::VertexArrayVk(ContextVk *contextVk, const gl::VertexArrayState &state)
    : VertexArrayImpl(state),
      mCurrentArrayBufferHandles{},
      mCurrentArrayBufferOffsets{},
      mCurrentArrayBuffers{},
      mCurrentArrayBufferConversion{{
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
          INIT,
      }},
      mCurrentArrayBufferConversionCanRelease{},
      mCurrentElementArrayBufferOffset(0),
      mCurrentElementArrayBuffer(nullptr),
      mDynamicVertexData(kVertexBufferUsageFlags, kDynamicVertexDataSize, true),
      mDynamicIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
      mTranslatedByteIndexData(kIndexBufferUsageFlags, kDynamicIndexDataSize, true),
      mLineLoopHelper(contextVk->getRenderer()),
      mDirtyLineLoopTranslation(true)
{
    RendererVk *renderer = contextVk->getRenderer();

    VkBufferCreateInfo createInfo = {};
    createInfo.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    createInfo.size               = 16;
    createInfo.usage              = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
    (void)mTheNullBuffer.init(contextVk, createInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);

    mCurrentArrayBufferHandles.fill(mTheNullBuffer.getBuffer().getHandle());
    mCurrentArrayBufferOffsets.fill(0);
    mCurrentArrayBuffers.fill(nullptr);

    for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
    {
        buffer.init(kMaxVertexFormatAlignment, renderer);
    }
    mDynamicVertexData.init(kMaxVertexFormatAlignment, renderer);
    mDynamicIndexData.init(1, renderer);
    mTranslatedByteIndexData.init(1, renderer);
}

VertexArrayVk::~VertexArrayVk() {}

void VertexArrayVk::destroy(const gl::Context *context)
{
    RendererVk *renderer = vk::GetImpl(context)->getRenderer();

    mTheNullBuffer.release(renderer);

    for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
    {
        buffer.release(renderer);
    }
    mDynamicVertexData.release(renderer);
    mDynamicIndexData.release(renderer);
    mTranslatedByteIndexData.release(renderer);
    mLineLoopHelper.release(renderer);
}

angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
                                             gl::DrawElementsType indexType,
                                             size_t indexCount,
                                             const void *sourcePointer,
                                             vk::DynamicBuffer *dynamicBuffer)
{
    ASSERT(!mState.getElementArrayBuffer() || indexType == gl::DrawElementsType::UnsignedByte);

    dynamicBuffer->releaseRetainedBuffers(contextVk->getRenderer());

    const size_t amount = sizeof(GLushort) * indexCount;
    GLubyte *dst        = nullptr;

    ANGLE_TRY(dynamicBuffer->allocate(contextVk, amount, &dst, nullptr,
                                      &mCurrentElementArrayBufferOffset, nullptr));
    mCurrentElementArrayBuffer = dynamicBuffer->getCurrentBuffer();
    if (indexType == gl::DrawElementsType::UnsignedByte)
    {
        // Unsigned bytes don't have direct support in Vulkan so we have to expand the
        // memory to a GLushort.
        const GLubyte *in     = static_cast<const GLubyte *>(sourcePointer);
        GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
        for (size_t index = 0; index < indexCount; index++)
        {
            expandedDst[index] = static_cast<GLushort>(in[index]);
        }
    }
    else
    {
        memcpy(dst, sourcePointer, amount);
    }
    ANGLE_TRY(dynamicBuffer->flush(contextVk));
    return angle::Result::Continue;
}

// We assume the buffer is completely full of the same kind of data and convert
// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
// but the alternative of copying it piecemeal on each draw would have a lot more
// overhead.
angle::Result VertexArrayVk::convertVertexBufferGpu(ContextVk *contextVk,
                                                    BufferVk *srcBuffer,
                                                    const gl::VertexBinding &binding,
                                                    size_t attribIndex,
                                                    const vk::Format &vertexFormat)
{
    RendererVk *renderer = contextVk->getRenderer();

    const angle::Format &srcFormat  = vertexFormat.angleFormat();
    const angle::Format &destFormat = vertexFormat.bufferFormat();

    ASSERT(binding.getStride() % (srcFormat.pixelBytes / srcFormat.channelCount()) == 0);

    unsigned srcFormatSize  = srcFormat.pixelBytes;
    unsigned destFormatSize = destFormat.pixelBytes;

    size_t numVertices = GetVertexCount(srcBuffer, binding, srcFormatSize);
    if (numVertices == 0)
    {
        return angle::Result::Continue;
    }

    ASSERT(GetVertexInputAlignment(vertexFormat) <= kMaxVertexFormatAlignment);

    // Allocate buffer for results
    mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(renderer);
    ANGLE_TRY(mCurrentArrayBufferConversion[attribIndex].allocate(
        contextVk, numVertices * destFormatSize, nullptr, nullptr,
        &mCurrentArrayBufferOffsets[attribIndex], nullptr));
    mCurrentArrayBuffers[attribIndex] =
        mCurrentArrayBufferConversion[attribIndex].getCurrentBuffer();

    UtilsVk::ConvertVertexParameters params;
    params.vertexCount = numVertices;
    params.srcFormat   = &srcFormat;
    params.destFormat  = &destFormat;
    params.srcStride   = binding.getStride();
    params.srcOffset   = binding.getOffset();
    params.destOffset  = static_cast<size_t>(mCurrentArrayBufferOffsets[attribIndex]);

    ANGLE_TRY(renderer->getUtils().convertVertexBuffer(contextVk, mCurrentArrayBuffers[attribIndex],
                                                       &srcBuffer->getBuffer(), params));

    mCurrentArrayBufferHandles[attribIndex] =
        mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle();
    mCurrentArrayBufferConversionCanRelease[attribIndex] = true;

    return angle::Result::Continue;
}

angle::Result VertexArrayVk::convertVertexBufferCpu(ContextVk *contextVk,
                                                    BufferVk *srcBuffer,
                                                    const gl::VertexBinding &binding,
                                                    size_t attribIndex,
                                                    const vk::Format &vertexFormat)
{
    TRACE_EVENT0("gpu.angle", "VertexArrayVk::convertVertexBufferCpu");
    // Needed before reading buffer or we could get stale data.
    ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));

    unsigned srcFormatSize = vertexFormat.angleFormat().pixelBytes;
    unsigned dstFormatSize = vertexFormat.bufferFormat().pixelBytes;

    mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());

    size_t numVertices = GetVertexCount(srcBuffer, binding, srcFormatSize);
    if (numVertices == 0)
    {
        return angle::Result::Continue;
    }

    void *src = nullptr;
    ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
    const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
    srcBytes += binding.getOffset();
    ASSERT(GetVertexInputAlignment(vertexFormat) <= kMaxVertexFormatAlignment);
    ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
                               numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
                               vertexFormat.vertexLoadFunction, &mCurrentArrayBuffers[attribIndex],
                               &mCurrentArrayBufferOffsets[attribIndex]));
    ANGLE_TRY(srcBuffer->unmapImpl(contextVk));

    mCurrentArrayBufferHandles[attribIndex] =
        mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle();
    mCurrentArrayBufferConversionCanRelease[attribIndex] = true;

    return angle::Result::Continue;
}

ANGLE_INLINE void VertexArrayVk::ensureConversionReleased(RendererVk *renderer, size_t attribIndex)
{
    if (mCurrentArrayBufferConversionCanRelease[attribIndex])
    {
        mCurrentArrayBufferConversion[attribIndex].release(renderer);
        mCurrentArrayBufferConversionCanRelease[attribIndex] = false;
    }
}

angle::Result VertexArrayVk::syncState(const gl::Context *context,
                                       const gl::VertexArray::DirtyBits &dirtyBits,
                                       gl::VertexArray::DirtyAttribBitsArray *attribBits,
                                       gl::VertexArray::DirtyBindingBitsArray *bindingBits)
{
    ASSERT(dirtyBits.any());

    bool invalidateContext = false;

    ContextVk *contextVk = vk::GetImpl(context);

    // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
    // TODO(jmadill): Handle buffer storage changes.
    const auto &attribs  = mState.getVertexAttributes();
    const auto &bindings = mState.getVertexBindings();

    for (size_t dirtyBit : dirtyBits)
    {
        switch (dirtyBit)
        {
            case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
            {
                gl::Buffer *bufferGL = mState.getElementArrayBuffer();
                if (bufferGL)
                {
                    BufferVk *bufferVk         = vk::GetImpl(bufferGL);
                    mCurrentElementArrayBuffer = &bufferVk->getBuffer();
                }
                else
                {
                    mCurrentElementArrayBuffer = nullptr;
                }

                mCurrentElementArrayBufferOffset = 0;
                mLineLoopBufferFirstIndex.reset();
                mLineLoopBufferLastIndex.reset();
                contextVk->setIndexBufferDirty();
                mDirtyLineLoopTranslation = true;
                break;
            }

            case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
                mLineLoopBufferFirstIndex.reset();
                mLineLoopBufferLastIndex.reset();
                mDirtyLineLoopTranslation = true;
                break;

#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX)                                     \
    case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:                             \
        ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX],                      \
                                  bindings[attribs[INDEX].bindingIndex], INDEX)); \
        invalidateContext = true;                                                 \
        (*attribBits)[INDEX].reset();                                             \
        break;

                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC)

#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX)                                    \
    case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX:                            \
        ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX],                      \
                                  bindings[attribs[INDEX].bindingIndex], INDEX)); \
        invalidateContext = true;                                                 \
        (*bindingBits)[INDEX].reset();                                            \
        break;

                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC)

#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX)                                \
    case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX:                        \
        ANGLE_TRY(syncDirtyAttrib(contextVk, attribs[INDEX],                      \
                                  bindings[attribs[INDEX].bindingIndex], INDEX)); \
        break;

                ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC)

            default:
                UNREACHABLE();
                break;
        }
    }

    if (invalidateContext)
    {
        contextVk->invalidateVertexAndIndexBuffers();
    }

    return angle::Result::Continue;
}

ANGLE_INLINE void VertexArrayVk::setDefaultPackedInput(ContextVk *contextVk, size_t attribIndex)
{
    contextVk->onVertexAttributeChange(attribIndex, 0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0);
}

angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
                                             const gl::VertexAttribute &attrib,
                                             const gl::VertexBinding &binding,
                                             size_t attribIndex)
{
    RendererVk *renderer               = contextVk->getRenderer();
    bool anyVertexBufferConvertedOnGpu = false;

    if (attrib.enabled)
    {
        gl::Buffer *bufferGL           = binding.getBuffer().get();
        const vk::Format &vertexFormat = renderer->getFormat(GetVertexFormatID(attrib));
        GLuint stride;

        if (bufferGL)
        {
            BufferVk *bufferVk               = vk::GetImpl(bufferGL);
            const angle::Format &angleFormat = vertexFormat.angleFormat();
            bool bindingIsAligned            = BindingIsAligned(binding, angleFormat, attrib.size);

            if (vertexFormat.vertexLoadRequiresConversion || !bindingIsAligned)
            {
                stride = vertexFormat.bufferFormat().pixelBytes;

                if (bindingIsAligned)
                {
                    ANGLE_TRY(convertVertexBufferGpu(contextVk, bufferVk, binding, attribIndex,
                                                     vertexFormat));
                    anyVertexBufferConvertedOnGpu = true;
                }
                else
                {
                    ANGLE_TRY(convertVertexBufferCpu(contextVk, bufferVk, binding, attribIndex,
                                                     vertexFormat));
                }
            }
            else
            {
                if (bufferVk->getSize() == 0)
                {
                    mCurrentArrayBuffers[attribIndex] = nullptr;
                    mCurrentArrayBufferHandles[attribIndex] =
                        mTheNullBuffer.getBuffer().getHandle();
                    mCurrentArrayBufferOffsets[attribIndex] = 0;
                    stride                                  = 0;
                }
                else
                {
                    mCurrentArrayBuffers[attribIndex] = &bufferVk->getBuffer();
                    mCurrentArrayBufferHandles[attribIndex] =
                        bufferVk->getBuffer().getBuffer().getHandle();
                    mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
                    stride                                  = binding.getStride();
                }

                ensureConversionReleased(renderer, attribIndex);
            }
        }
        else
        {
            mCurrentArrayBuffers[attribIndex]       = nullptr;
            mCurrentArrayBufferHandles[attribIndex] = mTheNullBuffer.getBuffer().getHandle();
            mCurrentArrayBufferOffsets[attribIndex] = 0;
            stride                                  = vertexFormat.bufferFormat().pixelBytes;
            ensureConversionReleased(renderer, attribIndex);
        }

        contextVk->onVertexAttributeChange(attribIndex, stride, binding.getDivisor(),
                                           vertexFormat.vkBufferFormat, attrib.relativeOffset);
    }
    else
    {
        contextVk->invalidateDefaultAttribute(attribIndex);

        // These will be filled out by the ContextVk.
        mCurrentArrayBuffers[attribIndex]       = nullptr;
        mCurrentArrayBufferHandles[attribIndex] = mTheNullBuffer.getBuffer().getHandle();
        mCurrentArrayBufferOffsets[attribIndex] = 0;

        setDefaultPackedInput(contextVk, attribIndex);
        ensureConversionReleased(renderer, attribIndex);
    }

    if (anyVertexBufferConvertedOnGpu && renderer->getFeatures().flushAfterVertexConversion)
    {
        ANGLE_TRY(renderer->flush(contextVk));
    }

    return angle::Result::Continue;
}

angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
                                                 GLint firstVertex,
                                                 GLsizei vertexOrIndexCount,
                                                 gl::DrawElementsType indexTypeOrInvalid,
                                                 const void *indices)
{
    ContextVk *contextVk                    = vk::GetImpl(context);
    const gl::AttributesMask &clientAttribs = context->getStateCache().getActiveClientAttribsMask();

    ASSERT(clientAttribs.any());

    GLint startVertex;
    size_t vertexCount;
    ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
                                 indices, 0, &startVertex, &vertexCount));

    RendererVk *renderer = contextVk->getRenderer();
    mDynamicVertexData.releaseRetainedBuffers(renderer);

    const auto &attribs  = mState.getVertexAttributes();
    const auto &bindings = mState.getVertexBindings();

    // TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
    // un-interleaved, wasting space and copying time.  Consider improving on that.
    for (size_t attribIndex : clientAttribs)
    {
        const gl::VertexAttribute &attrib = attribs[attribIndex];
        const gl::VertexBinding &binding  = bindings[attrib.bindingIndex];
        ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);

        const vk::Format &vertexFormat = renderer->getFormat(GetVertexFormatID(attrib));
        GLuint stride                  = vertexFormat.bufferFormat().pixelBytes;

        const size_t bytesToAllocate = (startVertex + vertexCount) * stride;
        const uint8_t *src =
            static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();

        size_t destOffset = startVertex * stride;
        ASSERT(GetVertexInputAlignment(vertexFormat) <= kMaxVertexFormatAlignment);

        // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
        // We allocate space for startVertex + vertexCount so indexing will work.  If we
        // don't start at zero all the indices will be off.
        // TODO(fjhenigman): See if we can account for indices being off by adjusting the
        // offset, thus avoiding wasted memory.
        ANGLE_TRY(StreamVertexData(
            contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
            binding.getStride(), vertexFormat.vertexLoadFunction,
            &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
        mCurrentArrayBufferHandles[attribIndex] =
            mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle();
    }

    return angle::Result::Continue;
}

angle::Result VertexArrayVk::handleLineLoop(ContextVk *contextVk,
                                            GLint firstVertex,
                                            GLsizei vertexOrIndexCount,
                                            gl::DrawElementsType indexTypeOrInvalid,
                                            const void *indices)
{
    if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
    {
        // Handle GL_LINE_LOOP drawElements.
        if (mDirtyLineLoopTranslation)
        {
            gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();

            if (!elementArrayBuffer)
            {
                ANGLE_TRY(mLineLoopHelper.streamIndices(
                    contextVk, indexTypeOrInvalid, vertexOrIndexCount,
                    reinterpret_cast<const uint8_t *>(indices), &mCurrentElementArrayBuffer,
                    &mCurrentElementArrayBufferOffset));
            }
            else
            {
                // When using an element array buffer, 'indices' is an offset to the first element.
                intptr_t offset                = reinterpret_cast<intptr_t>(indices);
                BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
                ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
                    contextVk, elementArrayBufferVk, indexTypeOrInvalid, vertexOrIndexCount, offset,
                    &mCurrentElementArrayBuffer, &mCurrentElementArrayBufferOffset));
            }
        }

        // If we've had a drawArrays call with a line loop before, we want to make sure this is
        // invalidated the next time drawArrays is called since we use the same index buffer for
        // both calls.
        mLineLoopBufferFirstIndex.reset();
        mLineLoopBufferLastIndex.reset();
        return angle::Result::Continue;
    }

    // Note: Vertex indexes can be arbitrarily large.
    uint32_t clampedVertexCount = gl::clampCast<uint32_t>(vertexOrIndexCount);

    // Handle GL_LINE_LOOP drawArrays.
    size_t lastVertex = static_cast<size_t>(firstVertex + clampedVertexCount);
    if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
        mLineLoopBufferFirstIndex != firstVertex || mLineLoopBufferLastIndex != lastVertex)
    {
        ANGLE_TRY(mLineLoopHelper.getIndexBufferForDrawArrays(
            contextVk, clampedVertexCount, firstVertex, &mCurrentElementArrayBuffer,
            &mCurrentElementArrayBufferOffset));

        mLineLoopBufferFirstIndex = firstVertex;
        mLineLoopBufferLastIndex  = lastVertex;
    }

    return angle::Result::Continue;
}

angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
                                                    GLsizei indexCount,
                                                    gl::DrawElementsType type,
                                                    const void *indices)
{
    ASSERT(type != gl::DrawElementsType::InvalidEnum);

    RendererVk *renderer = contextVk->getRenderer();
    gl::Buffer *glBuffer = mState.getElementArrayBuffer();

    if (!glBuffer)
    {
        ANGLE_TRY(streamIndexData(contextVk, type, indexCount, indices, &mDynamicIndexData));
    }
    else if (renderer->getFormat(angle::FormatID::R16_UINT).vkSupportsStorageBuffer)
    {
        BufferVk *bufferVk = vk::GetImpl(glBuffer);

        ASSERT(type == gl::DrawElementsType::UnsignedByte);

        intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
        size_t srcDataSize         = static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData;

        mTranslatedByteIndexData.releaseRetainedBuffers(renderer);

        ANGLE_TRY(mTranslatedByteIndexData.allocate(contextVk, sizeof(GLushort) * srcDataSize,
                                                    nullptr, nullptr,
                                                    &mCurrentElementArrayBufferOffset, nullptr));
        mCurrentElementArrayBuffer = mTranslatedByteIndexData.getCurrentBuffer();

        vk::BufferHelper *dest = mTranslatedByteIndexData.getCurrentBuffer();
        vk::BufferHelper *src  = &bufferVk->getBuffer();

        ANGLE_TRY(src->initBufferView(contextVk, renderer->getFormat(angle::FormatID::R8_UINT)));
        ANGLE_TRY(dest->initBufferView(contextVk, renderer->getFormat(angle::FormatID::R16_UINT)));

        // Copy relevant section of the source into destination at allocated offset.  Note that the
        // offset returned by allocate() above is in bytes, while our allocated array is of
        // GLushorts.
        UtilsVk::CopyParameters params = {};
        params.destOffset =
            static_cast<size_t>(mCurrentElementArrayBufferOffset) / sizeof(GLushort);
        params.srcOffset = offsetIntoSrcData;
        params.size      = srcDataSize;

        // Note: this is a copy, which implicitly converts between formats.  Once support for
        // primitive restart is added, a specialized shader is likely needed to special case 0xFF ->
        // 0xFFFF.
        ANGLE_TRY(renderer->getUtils().copyBuffer(contextVk, dest, src, params));
    }
    else
    {
        // If it's not possible to convert the buffer with compute, opt for a CPU read back for now.
        // TODO(syoussefi): R8G8B8A8_UINT is required to have storage texel buffer support, so a
        // specialized shader code can be made to read two ubyte indices and output them in R and B
        // (or A and G based on endianness?) with 0 on the other channels.  If specialized, we might
        // as well support the ubyte to ushort case with correct handling of primitive restart.
        // http://anglebug.com/3003

        TRACE_EVENT0("gpu.angle", "VertexArrayVk::updateIndexTranslation");
        // Needed before reading buffer or we could get stale data.
        ANGLE_TRY(renderer->finish(contextVk));

        ASSERT(type == gl::DrawElementsType::UnsignedByte);
        // Unsigned bytes don't have direct support in Vulkan so we have to expand the
        // memory to a GLushort.
        BufferVk *bufferVk   = vk::GetImpl(glBuffer);
        void *srcDataMapping = nullptr;
        ASSERT(!glBuffer->isMapped());
        ANGLE_TRY(bufferVk->mapImpl(contextVk, &srcDataMapping));
        uint8_t *srcData           = static_cast<uint8_t *>(srcDataMapping);
        intptr_t offsetIntoSrcData = reinterpret_cast<intptr_t>(indices);
        srcData += offsetIntoSrcData;

        ANGLE_TRY(streamIndexData(contextVk, type,
                                  static_cast<size_t>(bufferVk->getSize()) - offsetIntoSrcData,
                                  srcData, &mTranslatedByteIndexData));

        ANGLE_TRY(bufferVk->unmapImpl(contextVk));
    }

    return angle::Result::Continue;
}

void VertexArrayVk::updateDefaultAttrib(ContextVk *contextVk,
                                        size_t attribIndex,
                                        VkBuffer bufferHandle,
                                        uint32_t offset)
{
    if (!mState.getEnabledAttributesMask().test(attribIndex))
    {
        mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
        mCurrentArrayBufferOffsets[attribIndex] = offset;
        mCurrentArrayBuffers[attribIndex]       = nullptr;

        setDefaultPackedInput(contextVk, attribIndex);
    }
}
}  // namespace rx
