// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn_native/vulkan/CommandBufferVk.h"

#include "dawn_native/BindGroupTracker.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/CommandValidation.h"
#include "dawn_native/Commands.h"
#include "dawn_native/EnumMaskIterator.h"
#include "dawn_native/RenderBundle.h"
#include "dawn_native/vulkan/BindGroupVk.h"
#include "dawn_native/vulkan/BufferVk.h"
#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/ComputePipelineVk.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/PipelineLayoutVk.h"
#include "dawn_native/vulkan/QuerySetVk.h"
#include "dawn_native/vulkan/RenderPassCache.h"
#include "dawn_native/vulkan/RenderPipelineVk.h"
#include "dawn_native/vulkan/TextureVk.h"
#include "dawn_native/vulkan/UtilsVulkan.h"
#include "dawn_native/vulkan/VulkanError.h"

#include <algorithm>

namespace dawn_native { namespace vulkan {

    namespace {

        VkIndexType VulkanIndexType(wgpu::IndexFormat format) {
            switch (format) {
                case wgpu::IndexFormat::Uint16:
                    return VK_INDEX_TYPE_UINT16;
                case wgpu::IndexFormat::Uint32:
                    return VK_INDEX_TYPE_UINT32;
                case wgpu::IndexFormat::Undefined:
                    UNREACHABLE();
            }
        }

        bool HasSameTextureCopyExtent(const TextureCopy& srcCopy,
                                      const TextureCopy& dstCopy,
                                      const Extent3D& copySize) {
            Extent3D imageExtentSrc = ComputeTextureCopyExtent(srcCopy, copySize);
            Extent3D imageExtentDst = ComputeTextureCopyExtent(dstCopy, copySize);
            return imageExtentSrc.width == imageExtentDst.width &&
                   imageExtentSrc.height == imageExtentDst.height &&
                   imageExtentSrc.depthOrArrayLayers == imageExtentDst.depthOrArrayLayers;
        }

        VkImageCopy ComputeImageCopyRegion(const TextureCopy& srcCopy,
                                           const TextureCopy& dstCopy,
                                           const Extent3D& copySize,
                                           Aspect aspect) {
            const Texture* srcTexture = ToBackend(srcCopy.texture.Get());
            const Texture* dstTexture = ToBackend(dstCopy.texture.Get());

            VkImageCopy region;
            region.srcSubresource.aspectMask = VulkanAspectMask(aspect);
            region.srcSubresource.mipLevel = srcCopy.mipLevel;
            region.dstSubresource.aspectMask = VulkanAspectMask(aspect);
            region.dstSubresource.mipLevel = dstCopy.mipLevel;

            bool has3DTextureInCopy = false;

            region.srcOffset.x = srcCopy.origin.x;
            region.srcOffset.y = srcCopy.origin.y;
            switch (srcTexture->GetDimension()) {
                case wgpu::TextureDimension::e2D:
                    region.srcSubresource.baseArrayLayer = srcCopy.origin.z;
                    region.srcSubresource.layerCount = copySize.depthOrArrayLayers;
                    region.srcOffset.z = 0;
                    break;
                case wgpu::TextureDimension::e3D:
                    has3DTextureInCopy = true;
                    region.srcSubresource.baseArrayLayer = 0;
                    region.srcSubresource.layerCount = 1;
                    region.srcOffset.z = srcCopy.origin.z;
                    break;
                case wgpu::TextureDimension::e1D:
                    // TODO(jiawei.shao@intel.com): support 1D textures
                    UNREACHABLE();
            }

            region.dstOffset.x = dstCopy.origin.x;
            region.dstOffset.y = dstCopy.origin.y;
            switch (dstTexture->GetDimension()) {
                case wgpu::TextureDimension::e2D:
                    region.dstSubresource.baseArrayLayer = dstCopy.origin.z;
                    region.dstSubresource.layerCount = copySize.depthOrArrayLayers;
                    region.dstOffset.z = 0;
                    break;
                case wgpu::TextureDimension::e3D:
                    has3DTextureInCopy = true;
                    region.dstSubresource.baseArrayLayer = 0;
                    region.dstSubresource.layerCount = 1;
                    region.dstOffset.z = dstCopy.origin.z;
                    break;
                case wgpu::TextureDimension::e1D:
                    // TODO(jiawei.shao@intel.com): support 1D textures
                    UNREACHABLE();
            }

            ASSERT(HasSameTextureCopyExtent(srcCopy, dstCopy, copySize));
            Extent3D imageExtent = ComputeTextureCopyExtent(dstCopy, copySize);
            region.extent.width = imageExtent.width;
            region.extent.height = imageExtent.height;
            region.extent.depth = has3DTextureInCopy ? copySize.depthOrArrayLayers : 1;

            return region;
        }

        class DescriptorSetTracker : public BindGroupTrackerBase<true, uint32_t> {
          public:
            DescriptorSetTracker() = default;

            void Apply(Device* device,
                       CommandRecordingContext* recordingContext,
                       VkPipelineBindPoint bindPoint) {
                for (BindGroupIndex dirtyIndex :
                     IterateBitSet(mDirtyBindGroupsObjectChangedOrIsDynamic)) {
                    VkDescriptorSet set = ToBackend(mBindGroups[dirtyIndex])->GetHandle();
                    const uint32_t* dynamicOffset = mDynamicOffsetCounts[dirtyIndex] > 0
                                                        ? mDynamicOffsets[dirtyIndex].data()
                                                        : nullptr;
                    device->fn.CmdBindDescriptorSets(
                        recordingContext->commandBuffer, bindPoint,
                        ToBackend(mPipelineLayout)->GetHandle(), static_cast<uint32_t>(dirtyIndex),
                        1, &*set, mDynamicOffsetCounts[dirtyIndex], dynamicOffset);
                }
                DidApply();
            }
        };

        // Records the necessary barriers for a synchronization scope using the resource usage
        // data pre-computed in the frontend. Also performs lazy initialization if required.
        void TransitionAndClearForSyncScope(Device* device,
                                            CommandRecordingContext* recordingContext,
                                            const SyncScopeResourceUsage& scope) {
            std::vector<VkBufferMemoryBarrier> bufferBarriers;
            std::vector<VkImageMemoryBarrier> imageBarriers;
            VkPipelineStageFlags srcStages = 0;
            VkPipelineStageFlags dstStages = 0;

            for (size_t i = 0; i < scope.buffers.size(); ++i) {
                Buffer* buffer = ToBackend(scope.buffers[i]);
                buffer->EnsureDataInitialized(recordingContext);

                VkBufferMemoryBarrier bufferBarrier;
                if (buffer->TransitionUsageAndGetResourceBarrier(
                        scope.bufferUsages[i], &bufferBarrier, &srcStages, &dstStages)) {
                    bufferBarriers.push_back(bufferBarrier);
                }
            }

            for (size_t i = 0; i < scope.textures.size(); ++i) {
                Texture* texture = ToBackend(scope.textures[i]);

                // Clear subresources that are not render attachments. Render attachments will be
                // cleared in RecordBeginRenderPass by setting the loadop to clear when the texture
                // subresource has not been initialized before the render pass.
                scope.textureUsages[i].Iterate(
                    [&](const SubresourceRange& range, wgpu::TextureUsage usage) {
                        if (usage & ~wgpu::TextureUsage::RenderAttachment) {
                            texture->EnsureSubresourceContentInitialized(recordingContext, range);
                        }
                    });
                texture->TransitionUsageForPass(recordingContext, scope.textureUsages[i],
                                                &imageBarriers, &srcStages, &dstStages);
            }

            if (bufferBarriers.size() || imageBarriers.size()) {
                device->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages,
                                              0, 0, nullptr, bufferBarriers.size(),
                                              bufferBarriers.data(), imageBarriers.size(),
                                              imageBarriers.data());
            }
        }

        MaybeError RecordBeginRenderPass(CommandRecordingContext* recordingContext,
                                         Device* device,
                                         BeginRenderPassCmd* renderPass) {
            VkCommandBuffer commands = recordingContext->commandBuffer;

            // Query a VkRenderPass from the cache
            VkRenderPass renderPassVK = VK_NULL_HANDLE;
            {
                RenderPassCacheQuery query;

                for (ColorAttachmentIndex i :
                     IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
                    const auto& attachmentInfo = renderPass->colorAttachments[i];

                    bool hasResolveTarget = attachmentInfo.resolveTarget != nullptr;
                    wgpu::LoadOp loadOp = attachmentInfo.loadOp;

                    query.SetColor(i, attachmentInfo.view->GetFormat().format, loadOp,
                                   hasResolveTarget);
                }

                if (renderPass->attachmentState->HasDepthStencilAttachment()) {
                    const auto& attachmentInfo = renderPass->depthStencilAttachment;

                    query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat().format,
                                          attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp);
                }

                query.SetSampleCount(renderPass->attachmentState->GetSampleCount());

                DAWN_TRY_ASSIGN(renderPassVK, device->GetRenderPassCache()->GetRenderPass(query));
            }

            // Create a framebuffer that will be used once for the render pass and gather the clear
            // values for the attachments at the same time.
            std::array<VkClearValue, kMaxColorAttachments + 1> clearValues;
            VkFramebuffer framebuffer = VK_NULL_HANDLE;
            uint32_t attachmentCount = 0;
            {
                // Fill in the attachment info that will be chained in the framebuffer create info.
                std::array<VkImageView, kMaxColorAttachments * 2 + 1> attachments;

                for (ColorAttachmentIndex i :
                     IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
                    auto& attachmentInfo = renderPass->colorAttachments[i];
                    TextureView* view = ToBackend(attachmentInfo.view.Get());

                    attachments[attachmentCount] = view->GetHandle();

                    switch (view->GetFormat().GetAspectInfo(Aspect::Color).baseType) {
                        case wgpu::TextureComponentType::Float: {
                            const std::array<float, 4> appliedClearColor =
                                ConvertToFloatColor(attachmentInfo.clearColor);
                            for (uint32_t i = 0; i < 4; ++i) {
                                clearValues[attachmentCount].color.float32[i] =
                                    appliedClearColor[i];
                            }
                            break;
                        }
                        case wgpu::TextureComponentType::Uint: {
                            const std::array<uint32_t, 4> appliedClearColor =
                                ConvertToUnsignedIntegerColor(attachmentInfo.clearColor);
                            for (uint32_t i = 0; i < 4; ++i) {
                                clearValues[attachmentCount].color.uint32[i] = appliedClearColor[i];
                            }
                            break;
                        }
                        case wgpu::TextureComponentType::Sint: {
                            const std::array<int32_t, 4> appliedClearColor =
                                ConvertToSignedIntegerColor(attachmentInfo.clearColor);
                            for (uint32_t i = 0; i < 4; ++i) {
                                clearValues[attachmentCount].color.int32[i] = appliedClearColor[i];
                            }
                            break;
                        }

                        case wgpu::TextureComponentType::DepthComparison:
                            UNREACHABLE();
                    }
                    attachmentCount++;
                }

                if (renderPass->attachmentState->HasDepthStencilAttachment()) {
                    auto& attachmentInfo = renderPass->depthStencilAttachment;
                    TextureView* view = ToBackend(attachmentInfo.view.Get());

                    attachments[attachmentCount] = view->GetHandle();

                    clearValues[attachmentCount].depthStencil.depth = attachmentInfo.clearDepth;
                    clearValues[attachmentCount].depthStencil.stencil = attachmentInfo.clearStencil;

                    attachmentCount++;
                }

                for (ColorAttachmentIndex i :
                     IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
                    if (renderPass->colorAttachments[i].resolveTarget != nullptr) {
                        TextureView* view =
                            ToBackend(renderPass->colorAttachments[i].resolveTarget.Get());

                        attachments[attachmentCount] = view->GetHandle();

                        attachmentCount++;
                    }
                }

                // Chain attachments and create the framebuffer
                VkFramebufferCreateInfo createInfo;
                createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
                createInfo.pNext = nullptr;
                createInfo.flags = 0;
                createInfo.renderPass = renderPassVK;
                createInfo.attachmentCount = attachmentCount;
                createInfo.pAttachments = AsVkArray(attachments.data());
                createInfo.width = renderPass->width;
                createInfo.height = renderPass->height;
                createInfo.layers = 1;

                DAWN_TRY(
                    CheckVkSuccess(device->fn.CreateFramebuffer(device->GetVkDevice(), &createInfo,
                                                                nullptr, &*framebuffer),
                                   "CreateFramebuffer"));

                // We don't reuse VkFramebuffers so mark the framebuffer for deletion as soon as the
                // commands currently being recorded are finished.
                device->GetFencedDeleter()->DeleteWhenUnused(framebuffer);
            }

            VkRenderPassBeginInfo beginInfo;
            beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
            beginInfo.pNext = nullptr;
            beginInfo.renderPass = renderPassVK;
            beginInfo.framebuffer = framebuffer;
            beginInfo.renderArea.offset.x = 0;
            beginInfo.renderArea.offset.y = 0;
            beginInfo.renderArea.extent.width = renderPass->width;
            beginInfo.renderArea.extent.height = renderPass->height;
            beginInfo.clearValueCount = attachmentCount;
            beginInfo.pClearValues = clearValues.data();

            device->fn.CmdBeginRenderPass(commands, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);

            return {};
        }

        // Reset the query sets used on render pass because the reset command must be called outside
        // render pass.
        void ResetUsedQuerySetsOnRenderPass(Device* device,
                                            VkCommandBuffer commands,
                                            QuerySetBase* querySet,
                                            const std::vector<bool>& availability) {
            ASSERT(availability.size() == querySet->GetQueryAvailability().size());

            auto currentIt = availability.begin();
            auto lastIt = availability.end();
            // Traverse the used queries which availability are true.
            while (currentIt != lastIt) {
                auto firstTrueIt = std::find(currentIt, lastIt, true);
                // No used queries need to be reset
                if (firstTrueIt == lastIt) {
                    break;
                }

                auto nextFalseIt = std::find(firstTrueIt, lastIt, false);

                uint32_t queryIndex = std::distance(availability.begin(), firstTrueIt);
                uint32_t queryCount = std::distance(firstTrueIt, nextFalseIt);

                // Reset the queries between firstTrueIt and nextFalseIt (which is at most
                // lastIt)
                device->fn.CmdResetQueryPool(commands, ToBackend(querySet)->GetHandle(), queryIndex,
                                             queryCount);

                // Set current iterator to next false
                currentIt = nextFalseIt;
            }
        }

        void RecordWriteTimestampCmd(CommandRecordingContext* recordingContext,
                                     Device* device,
                                     WriteTimestampCmd* cmd) {
            VkCommandBuffer commands = recordingContext->commandBuffer;
            QuerySet* querySet = ToBackend(cmd->querySet.Get());

            device->fn.CmdWriteTimestamp(commands, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                                         querySet->GetHandle(), cmd->queryIndex);
        }

        void RecordResolveQuerySetCmd(VkCommandBuffer commands,
                                      Device* device,
                                      QuerySet* querySet,
                                      uint32_t firstQuery,
                                      uint32_t queryCount,
                                      Buffer* destination,
                                      uint64_t destinationOffset) {
            const std::vector<bool>& availability = querySet->GetQueryAvailability();

            auto currentIt = availability.begin() + firstQuery;
            auto lastIt = availability.begin() + firstQuery + queryCount;

            // Traverse available queries in the range of [firstQuery, firstQuery +  queryCount - 1]
            while (currentIt != lastIt) {
                auto firstTrueIt = std::find(currentIt, lastIt, true);
                // No available query found for resolving
                if (firstTrueIt == lastIt) {
                    break;
                }
                auto nextFalseIt = std::find(firstTrueIt, lastIt, false);

                // The query index of firstTrueIt where the resolving starts
                uint32_t resolveQueryIndex = std::distance(availability.begin(), firstTrueIt);
                // The queries count between firstTrueIt and nextFalseIt need to be resolved
                uint32_t resolveQueryCount = std::distance(firstTrueIt, nextFalseIt);

                // Calculate destinationOffset based on the current resolveQueryIndex and firstQuery
                uint32_t resolveDestinationOffset =
                    destinationOffset + (resolveQueryIndex - firstQuery) * sizeof(uint64_t);

                // Resolve the queries between firstTrueIt and nextFalseIt (which is at most lastIt)
                device->fn.CmdCopyQueryPoolResults(
                    commands, querySet->GetHandle(), resolveQueryIndex, resolveQueryCount,
                    destination->GetHandle(), resolveDestinationOffset, sizeof(uint64_t),
                    VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);

                // Set current iterator to next false
                currentIt = nextFalseIt;
            }
        }

    }  // anonymous namespace

    // static
    Ref<CommandBuffer> CommandBuffer::Create(CommandEncoder* encoder,
                                             const CommandBufferDescriptor* descriptor) {
        return AcquireRef(new CommandBuffer(encoder, descriptor));
    }

    CommandBuffer::CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor)
        : CommandBufferBase(encoder, descriptor) {
    }

    void CommandBuffer::RecordCopyImageWithTemporaryBuffer(
        CommandRecordingContext* recordingContext,
        const TextureCopy& srcCopy,
        const TextureCopy& dstCopy,
        const Extent3D& copySize) {
        ASSERT(srcCopy.texture->GetFormat().format == dstCopy.texture->GetFormat().format);
        ASSERT(srcCopy.aspect == dstCopy.aspect);
        dawn_native::Format format = srcCopy.texture->GetFormat();
        const TexelBlockInfo& blockInfo = format.GetAspectInfo(srcCopy.aspect).block;
        ASSERT(copySize.width % blockInfo.width == 0);
        uint32_t widthInBlocks = copySize.width / blockInfo.width;
        ASSERT(copySize.height % blockInfo.height == 0);
        uint32_t heightInBlocks = copySize.height / blockInfo.height;

        // Create the temporary buffer. Note that We don't need to respect WebGPU's 256 alignment
        // because it isn't a hard constraint in Vulkan.
        uint64_t tempBufferSize =
            widthInBlocks * heightInBlocks * copySize.depthOrArrayLayers * blockInfo.byteSize;
        BufferDescriptor tempBufferDescriptor;
        tempBufferDescriptor.size = tempBufferSize;
        tempBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;

        Device* device = ToBackend(GetDevice());
        // TODO(dawn:723): change to not use AcquireRef for reentrant object creation.
        Ref<Buffer> tempBuffer =
            AcquireRef(ToBackend(device->APICreateBuffer(&tempBufferDescriptor)));

        BufferCopy tempBufferCopy;
        tempBufferCopy.buffer = tempBuffer.Get();
        tempBufferCopy.rowsPerImage = heightInBlocks;
        tempBufferCopy.offset = 0;
        tempBufferCopy.bytesPerRow = copySize.width / blockInfo.width * blockInfo.byteSize;

        VkCommandBuffer commands = recordingContext->commandBuffer;
        VkImage srcImage = ToBackend(srcCopy.texture)->GetHandle();
        VkImage dstImage = ToBackend(dstCopy.texture)->GetHandle();

        tempBuffer->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopyDst);
        VkBufferImageCopy srcToTempBufferRegion =
            ComputeBufferImageCopyRegion(tempBufferCopy, srcCopy, copySize);

        // The Dawn CopySrc usage is always mapped to GENERAL
        device->fn.CmdCopyImageToBuffer(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL,
                                        tempBuffer->GetHandle(), 1, &srcToTempBufferRegion);

        tempBuffer->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopySrc);
        VkBufferImageCopy tempBufferToDstRegion =
            ComputeBufferImageCopyRegion(tempBufferCopy, dstCopy, copySize);

        // Dawn guarantees dstImage be in the TRANSFER_DST_OPTIMAL layout after the
        // copy command.
        device->fn.CmdCopyBufferToImage(commands, tempBuffer->GetHandle(), dstImage,
                                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
                                        &tempBufferToDstRegion);

        recordingContext->tempBuffers.emplace_back(tempBuffer);
    }

    MaybeError CommandBuffer::RecordCommands(CommandRecordingContext* recordingContext) {
        Device* device = ToBackend(GetDevice());
        VkCommandBuffer commands = recordingContext->commandBuffer;

        // Records the necessary barriers for the resource usage pre-computed by the frontend.
        // And resets the used query sets which are rewritten on the render pass.
        auto PrepareResourcesForRenderPass = [](Device* device,
                                                CommandRecordingContext* recordingContext,
                                                const RenderPassResourceUsage& usages) {
            TransitionAndClearForSyncScope(device, recordingContext, usages);

            // Reset all query set used on current render pass together before beginning render pass
            // because the reset command must be called outside render pass
            for (size_t i = 0; i < usages.querySets.size(); ++i) {
                ResetUsedQuerySetsOnRenderPass(device, recordingContext->commandBuffer,
                                               usages.querySets[i], usages.queryAvailabilities[i]);
            }
        };

        size_t nextComputePassNumber = 0;
        size_t nextRenderPassNumber = 0;

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::CopyBufferToBuffer: {
                    CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();

                    Buffer* srcBuffer = ToBackend(copy->source.Get());
                    Buffer* dstBuffer = ToBackend(copy->destination.Get());

                    srcBuffer->EnsureDataInitialized(recordingContext);
                    dstBuffer->EnsureDataInitializedAsDestination(
                        recordingContext, copy->destinationOffset, copy->size);

                    srcBuffer->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopySrc);
                    dstBuffer->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopyDst);

                    VkBufferCopy region;
                    region.srcOffset = copy->sourceOffset;
                    region.dstOffset = copy->destinationOffset;
                    region.size = copy->size;

                    VkBuffer srcHandle = srcBuffer->GetHandle();
                    VkBuffer dstHandle = dstBuffer->GetHandle();
                    device->fn.CmdCopyBuffer(commands, srcHandle, dstHandle, 1, &region);
                    break;
                }

                case Command::CopyBufferToTexture: {
                    CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    ToBackend(src.buffer)->EnsureDataInitialized(recordingContext);

                    VkBufferImageCopy region =
                        ComputeBufferImageCopyRegion(src, dst, copy->copySize);
                    VkImageSubresourceLayers subresource = region.imageSubresource;

                    ASSERT(dst.texture->GetDimension() != wgpu::TextureDimension::e1D);
                    SubresourceRange range =
                        GetSubresourcesAffectedByCopy(copy->destination, copy->copySize);

                    if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize,
                                                      subresource.mipLevel)) {
                        // Since texture has been overwritten, it has been "initialized"
                        dst.texture->SetIsSubresourceContentInitialized(true, range);
                    } else {
                        ToBackend(dst.texture)
                            ->EnsureSubresourceContentInitialized(recordingContext, range);
                    }
                    ToBackend(src.buffer)
                        ->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopySrc);
                    ToBackend(dst.texture)
                        ->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst, range);
                    VkBuffer srcBuffer = ToBackend(src.buffer)->GetHandle();
                    VkImage dstImage = ToBackend(dst.texture)->GetHandle();

                    // Dawn guarantees dstImage be in the TRANSFER_DST_OPTIMAL layout after the
                    // copy command.
                    device->fn.CmdCopyBufferToImage(commands, srcBuffer, dstImage,
                                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
                                                    &region);
                    break;
                }

                case Command::CopyTextureToBuffer: {
                    CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    ToBackend(dst.buffer)
                        ->EnsureDataInitializedAsDestination(recordingContext, copy);

                    VkBufferImageCopy region =
                        ComputeBufferImageCopyRegion(dst, src, copy->copySize);

                    ASSERT(src.texture->GetDimension() != wgpu::TextureDimension::e1D);
                    SubresourceRange range =
                        GetSubresourcesAffectedByCopy(copy->source, copy->copySize);

                    ToBackend(src.texture)
                        ->EnsureSubresourceContentInitialized(recordingContext, range);

                    ToBackend(src.texture)
                        ->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopySrc, range);
                    ToBackend(dst.buffer)
                        ->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopyDst);

                    VkImage srcImage = ToBackend(src.texture)->GetHandle();
                    VkBuffer dstBuffer = ToBackend(dst.buffer)->GetHandle();
                    // The Dawn CopySrc usage is always mapped to GENERAL
                    device->fn.CmdCopyImageToBuffer(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL,
                                                    dstBuffer, 1, &region);
                    break;
                }

                case Command::CopyTextureToTexture: {
                    CopyTextureToTextureCmd* copy =
                        mCommands.NextCommand<CopyTextureToTextureCmd>();
                    TextureCopy& src = copy->source;
                    TextureCopy& dst = copy->destination;
                    SubresourceRange srcRange = GetSubresourcesAffectedByCopy(src, copy->copySize);
                    SubresourceRange dstRange = GetSubresourcesAffectedByCopy(dst, copy->copySize);

                    ToBackend(src.texture)
                        ->EnsureSubresourceContentInitialized(recordingContext, srcRange);
                    if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize,
                                                      dst.mipLevel)) {
                        // Since destination texture has been overwritten, it has been "initialized"
                        dst.texture->SetIsSubresourceContentInitialized(true, dstRange);
                    } else {
                        ToBackend(dst.texture)
                            ->EnsureSubresourceContentInitialized(recordingContext, dstRange);
                    }

                    if (src.texture.Get() == dst.texture.Get() && src.mipLevel == dst.mipLevel) {
                        // When there are overlapped subresources, the layout of the overlapped
                        // subresources should all be GENERAL instead of what we set now. Currently
                        // it is not allowed to copy with overlapped subresources, but we still
                        // add the ASSERT here as a reminder for this possible misuse.
                        ASSERT(!IsRangeOverlapped(src.origin.z, dst.origin.z,
                                                  copy->copySize.depthOrArrayLayers));
                    }

                    // TODO after Yunchao's CL
                    ToBackend(src.texture)
                        ->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopySrc,
                                             srcRange);
                    ToBackend(dst.texture)
                        ->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst,
                                             dstRange);

                    // In some situations we cannot do texture-to-texture copies with vkCmdCopyImage
                    // because as Vulkan SPEC always validates image copies with the virtual size of
                    // the image subresource, when the extent that fits in the copy region of one
                    // subresource but does not fit in the one of another subresource, we will fail
                    // to find a valid extent to satisfy the requirements on both source and
                    // destination image subresource. For example, when the source is the first
                    // level of a 16x16 texture in BC format, and the destination is the third level
                    // of a 60x60 texture in the same format, neither 16x16 nor 15x15 is valid as
                    // the extent of vkCmdCopyImage.
                    // Our workaround for this issue is replacing the texture-to-texture copy with
                    // one texture-to-buffer copy and one buffer-to-texture copy.
                    bool copyUsingTemporaryBuffer =
                        device->IsToggleEnabled(
                            Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy) &&
                        src.texture->GetFormat().isCompressed &&
                        !HasSameTextureCopyExtent(src, dst, copy->copySize);

                    if (!copyUsingTemporaryBuffer) {
                        VkImage srcImage = ToBackend(src.texture)->GetHandle();
                        VkImage dstImage = ToBackend(dst.texture)->GetHandle();

                        for (Aspect aspect : IterateEnumMask(src.texture->GetFormat().aspects)) {
                            ASSERT(dst.texture->GetFormat().aspects & aspect);
                            VkImageCopy region =
                                ComputeImageCopyRegion(src, dst, copy->copySize, aspect);

                            // Dawn guarantees dstImage be in the TRANSFER_DST_OPTIMAL layout after
                            // the copy command.
                            device->fn.CmdCopyImage(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL,
                                                    dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                                    1, &region);
                        }
                    } else {
                        RecordCopyImageWithTemporaryBuffer(recordingContext, src, dst,
                                                           copy->copySize);
                    }

                    break;
                }

                case Command::BeginRenderPass: {
                    BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();

                    PrepareResourcesForRenderPass(
                        device, recordingContext,
                        GetResourceUsages().renderPasses[nextRenderPassNumber]);

                    LazyClearRenderPassAttachments(cmd);
                    DAWN_TRY(RecordRenderPass(recordingContext, cmd));

                    nextRenderPassNumber++;
                    break;
                }

                case Command::BeginComputePass: {
                    mCommands.NextCommand<BeginComputePassCmd>();

                    DAWN_TRY(RecordComputePass(
                        recordingContext,
                        GetResourceUsages().computePasses[nextComputePassNumber]));

                    nextComputePassNumber++;
                    break;
                }

                case Command::ResolveQuerySet: {
                    ResolveQuerySetCmd* cmd = mCommands.NextCommand<ResolveQuerySetCmd>();
                    QuerySet* querySet = ToBackend(cmd->querySet.Get());
                    Buffer* destination = ToBackend(cmd->destination.Get());

                    // vkCmdCopyQueryPoolResults only can retrieve available queries because
                    // VK_QUERY_RESULT_WAIT_BIT is set, for these unavailable queries, we need to
                    // clear the resolving region of the buffer to 0s if the buffer has been
                    // initialized or fully used.
                    auto startIt = querySet->GetQueryAvailability().begin() + cmd->firstQuery;
                    auto endIt = querySet->GetQueryAvailability().begin() + cmd->firstQuery +
                                 cmd->queryCount;
                    bool hasUnavailableQueries = std::find(startIt, endIt, false) != endIt;
                    if (hasUnavailableQueries &&
                        (destination->IsDataInitialized() ||
                         destination->IsFullBufferRange(cmd->destinationOffset,
                                                        cmd->queryCount * sizeof(uint64_t)))) {
                        destination->TransitionUsageNow(recordingContext,
                                                        wgpu::BufferUsage::CopyDst);
                        device->fn.CmdFillBuffer(commands, destination->GetHandle(),
                                                 cmd->destinationOffset,
                                                 cmd->queryCount * sizeof(uint64_t), 0u);
                    } else {
                        destination->EnsureDataInitializedAsDestination(
                            recordingContext, cmd->destinationOffset,
                            cmd->queryCount * sizeof(uint64_t));
                    }

                    destination->TransitionUsageNow(recordingContext,
                                                    wgpu::BufferUsage::QueryResolve);

                    RecordResolveQuerySetCmd(commands, device, querySet, cmd->firstQuery,
                                             cmd->queryCount, destination, cmd->destinationOffset);

                    break;
                }

                case Command::WriteTimestamp: {
                    WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();

                    // The query must be reset between uses.
                    device->fn.CmdResetQueryPool(commands, ToBackend(cmd->querySet)->GetHandle(),
                                                 cmd->queryIndex, 1);

                    RecordWriteTimestampCmd(recordingContext, device, cmd);
                    break;
                }

                case Command::InsertDebugMarker: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
                        const char* label = mCommands.NextData<char>(cmd->length + 1);
                        VkDebugUtilsLabelEXT utilsLabel;
                        utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                        utilsLabel.pNext = nullptr;
                        utilsLabel.pLabelName = label;
                        // Default color to black
                        utilsLabel.color[0] = 0.0;
                        utilsLabel.color[1] = 0.0;
                        utilsLabel.color[2] = 0.0;
                        utilsLabel.color[3] = 1.0;
                        device->fn.CmdInsertDebugUtilsLabelEXT(commands, &utilsLabel);
                    } else {
                        SkipCommand(&mCommands, Command::InsertDebugMarker);
                    }
                    break;
                }

                case Command::PopDebugGroup: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        mCommands.NextCommand<PopDebugGroupCmd>();
                        device->fn.CmdEndDebugUtilsLabelEXT(commands);
                    } else {
                        SkipCommand(&mCommands, Command::PopDebugGroup);
                    }
                    break;
                }

                case Command::PushDebugGroup: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
                        const char* label = mCommands.NextData<char>(cmd->length + 1);
                        VkDebugUtilsLabelEXT utilsLabel;
                        utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                        utilsLabel.pNext = nullptr;
                        utilsLabel.pLabelName = label;
                        // Default color to black
                        utilsLabel.color[0] = 0.0;
                        utilsLabel.color[1] = 0.0;
                        utilsLabel.color[2] = 0.0;
                        utilsLabel.color[3] = 1.0;
                        device->fn.CmdBeginDebugUtilsLabelEXT(commands, &utilsLabel);
                    } else {
                        SkipCommand(&mCommands, Command::PushDebugGroup);
                    }
                    break;
                }

                default:
                    break;
            }
        }

        return {};
    }

    MaybeError CommandBuffer::RecordComputePass(CommandRecordingContext* recordingContext,
                                                const ComputePassResourceUsage& resourceUsages) {
        Device* device = ToBackend(GetDevice());
        VkCommandBuffer commands = recordingContext->commandBuffer;

        uint64_t currentDispatch = 0;
        DescriptorSetTracker descriptorSets = {};

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::EndComputePass: {
                    mCommands.NextCommand<EndComputePassCmd>();
                    return {};
                }

                case Command::Dispatch: {
                    DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();

                    TransitionAndClearForSyncScope(device, recordingContext,
                                                   resourceUsages.dispatchUsages[currentDispatch]);
                    descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_COMPUTE);

                    device->fn.CmdDispatch(commands, dispatch->x, dispatch->y, dispatch->z);
                    currentDispatch++;
                    break;
                }

                case Command::DispatchIndirect: {
                    DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>();
                    VkBuffer indirectBuffer = ToBackend(dispatch->indirectBuffer)->GetHandle();

                    TransitionAndClearForSyncScope(device, recordingContext,
                                                   resourceUsages.dispatchUsages[currentDispatch]);
                    descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_COMPUTE);

                    device->fn.CmdDispatchIndirect(
                        commands, indirectBuffer,
                        static_cast<VkDeviceSize>(dispatch->indirectOffset));
                    currentDispatch++;
                    break;
                }

                case Command::SetBindGroup: {
                    SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();

                    BindGroup* bindGroup = ToBackend(cmd->group.Get());
                    uint32_t* dynamicOffsets = nullptr;
                    if (cmd->dynamicOffsetCount > 0) {
                        dynamicOffsets = mCommands.NextData<uint32_t>(cmd->dynamicOffsetCount);
                    }

                    descriptorSets.OnSetBindGroup(cmd->index, bindGroup, cmd->dynamicOffsetCount,
                                                  dynamicOffsets);
                    break;
                }

                case Command::SetComputePipeline: {
                    SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
                    ComputePipeline* pipeline = ToBackend(cmd->pipeline).Get();

                    device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_COMPUTE,
                                               pipeline->GetHandle());
                    descriptorSets.OnSetPipeline(pipeline);
                    break;
                }

                case Command::InsertDebugMarker: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
                        const char* label = mCommands.NextData<char>(cmd->length + 1);
                        VkDebugUtilsLabelEXT utilsLabel;
                        utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                        utilsLabel.pNext = nullptr;
                        utilsLabel.pLabelName = label;
                        // Default color to black
                        utilsLabel.color[0] = 0.0;
                        utilsLabel.color[1] = 0.0;
                        utilsLabel.color[2] = 0.0;
                        utilsLabel.color[3] = 1.0;
                        device->fn.CmdInsertDebugUtilsLabelEXT(commands, &utilsLabel);
                    } else {
                        SkipCommand(&mCommands, Command::InsertDebugMarker);
                    }
                    break;
                }

                case Command::PopDebugGroup: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        mCommands.NextCommand<PopDebugGroupCmd>();
                        device->fn.CmdEndDebugUtilsLabelEXT(commands);
                    } else {
                        SkipCommand(&mCommands, Command::PopDebugGroup);
                    }
                    break;
                }

                case Command::PushDebugGroup: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
                        const char* label = mCommands.NextData<char>(cmd->length + 1);
                        VkDebugUtilsLabelEXT utilsLabel;
                        utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                        utilsLabel.pNext = nullptr;
                        utilsLabel.pLabelName = label;
                        // Default color to black
                        utilsLabel.color[0] = 0.0;
                        utilsLabel.color[1] = 0.0;
                        utilsLabel.color[2] = 0.0;
                        utilsLabel.color[3] = 1.0;
                        device->fn.CmdBeginDebugUtilsLabelEXT(commands, &utilsLabel);
                    } else {
                        SkipCommand(&mCommands, Command::PushDebugGroup);
                    }
                    break;
                }

                case Command::WriteTimestamp: {
                    WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();

                    // The query must be reset between uses.
                    device->fn.CmdResetQueryPool(commands, ToBackend(cmd->querySet)->GetHandle(),
                                                 cmd->queryIndex, 1);

                    RecordWriteTimestampCmd(recordingContext, device, cmd);
                    break;
                }

                default:
                    UNREACHABLE();
            }
        }

        // EndComputePass should have been called
        UNREACHABLE();
    }

    MaybeError CommandBuffer::RecordRenderPass(CommandRecordingContext* recordingContext,
                                               BeginRenderPassCmd* renderPassCmd) {
        Device* device = ToBackend(GetDevice());
        VkCommandBuffer commands = recordingContext->commandBuffer;

        DAWN_TRY(RecordBeginRenderPass(recordingContext, device, renderPassCmd));

        // Set the default value for the dynamic state
        {
            device->fn.CmdSetLineWidth(commands, 1.0f);
            device->fn.CmdSetDepthBounds(commands, 0.0f, 1.0f);

            device->fn.CmdSetStencilReference(commands, VK_STENCIL_FRONT_AND_BACK, 0);

            float blendConstants[4] = {
                0.0f,
                0.0f,
                0.0f,
                0.0f,
            };
            device->fn.CmdSetBlendConstants(commands, blendConstants);

            // The viewport and scissor default to cover all of the attachments
            VkViewport viewport;
            viewport.x = 0.0f;
            viewport.y = static_cast<float>(renderPassCmd->height);
            viewport.width = static_cast<float>(renderPassCmd->width);
            viewport.height = -static_cast<float>(renderPassCmd->height);
            viewport.minDepth = 0.0f;
            viewport.maxDepth = 1.0f;
            device->fn.CmdSetViewport(commands, 0, 1, &viewport);

            VkRect2D scissorRect;
            scissorRect.offset.x = 0;
            scissorRect.offset.y = 0;
            scissorRect.extent.width = renderPassCmd->width;
            scissorRect.extent.height = renderPassCmd->height;
            device->fn.CmdSetScissor(commands, 0, 1, &scissorRect);
        }

        DescriptorSetTracker descriptorSets = {};
        RenderPipeline* lastPipeline = nullptr;

        auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
            switch (type) {
                case Command::Draw: {
                    DrawCmd* draw = iter->NextCommand<DrawCmd>();

                    descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_GRAPHICS);
                    device->fn.CmdDraw(commands, draw->vertexCount, draw->instanceCount,
                                       draw->firstVertex, draw->firstInstance);
                    break;
                }

                case Command::DrawIndexed: {
                    DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();

                    descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_GRAPHICS);
                    device->fn.CmdDrawIndexed(commands, draw->indexCount, draw->instanceCount,
                                              draw->firstIndex, draw->baseVertex,
                                              draw->firstInstance);
                    break;
                }

                case Command::DrawIndirect: {
                    DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
                    VkBuffer indirectBuffer = ToBackend(draw->indirectBuffer)->GetHandle();

                    descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_GRAPHICS);
                    device->fn.CmdDrawIndirect(commands, indirectBuffer,
                                               static_cast<VkDeviceSize>(draw->indirectOffset), 1,
                                               0);
                    break;
                }

                case Command::DrawIndexedIndirect: {
                    DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
                    VkBuffer indirectBuffer = ToBackend(draw->indirectBuffer)->GetHandle();

                    descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_GRAPHICS);
                    device->fn.CmdDrawIndexedIndirect(
                        commands, indirectBuffer, static_cast<VkDeviceSize>(draw->indirectOffset),
                        1, 0);
                    break;
                }

                case Command::InsertDebugMarker: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
                        const char* label = iter->NextData<char>(cmd->length + 1);
                        VkDebugUtilsLabelEXT utilsLabel;
                        utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                        utilsLabel.pNext = nullptr;
                        utilsLabel.pLabelName = label;
                        // Default color to black
                        utilsLabel.color[0] = 0.0;
                        utilsLabel.color[1] = 0.0;
                        utilsLabel.color[2] = 0.0;
                        utilsLabel.color[3] = 1.0;
                        device->fn.CmdInsertDebugUtilsLabelEXT(commands, &utilsLabel);
                    } else {
                        SkipCommand(iter, Command::InsertDebugMarker);
                    }
                    break;
                }

                case Command::PopDebugGroup: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        iter->NextCommand<PopDebugGroupCmd>();
                        device->fn.CmdEndDebugUtilsLabelEXT(commands);
                    } else {
                        SkipCommand(iter, Command::PopDebugGroup);
                    }
                    break;
                }

                case Command::PushDebugGroup: {
                    if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                        PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
                        const char* label = iter->NextData<char>(cmd->length + 1);
                        VkDebugUtilsLabelEXT utilsLabel;
                        utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                        utilsLabel.pNext = nullptr;
                        utilsLabel.pLabelName = label;
                        // Default color to black
                        utilsLabel.color[0] = 0.0;
                        utilsLabel.color[1] = 0.0;
                        utilsLabel.color[2] = 0.0;
                        utilsLabel.color[3] = 1.0;
                        device->fn.CmdBeginDebugUtilsLabelEXT(commands, &utilsLabel);
                    } else {
                        SkipCommand(iter, Command::PushDebugGroup);
                    }
                    break;
                }

                case Command::SetBindGroup: {
                    SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
                    BindGroup* bindGroup = ToBackend(cmd->group.Get());
                    uint32_t* dynamicOffsets = nullptr;
                    if (cmd->dynamicOffsetCount > 0) {
                        dynamicOffsets = iter->NextData<uint32_t>(cmd->dynamicOffsetCount);
                    }

                    descriptorSets.OnSetBindGroup(cmd->index, bindGroup, cmd->dynamicOffsetCount,
                                                  dynamicOffsets);
                    break;
                }

                case Command::SetIndexBuffer: {
                    SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
                    VkBuffer indexBuffer = ToBackend(cmd->buffer)->GetHandle();

                    device->fn.CmdBindIndexBuffer(commands, indexBuffer, cmd->offset,
                                                  VulkanIndexType(cmd->format));
                    break;
                }

                case Command::SetRenderPipeline: {
                    SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
                    RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();

                    device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS,
                                               pipeline->GetHandle());
                    lastPipeline = pipeline;

                    descriptorSets.OnSetPipeline(pipeline);
                    break;
                }

                case Command::SetVertexBuffer: {
                    SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();
                    VkBuffer buffer = ToBackend(cmd->buffer)->GetHandle();
                    VkDeviceSize offset = static_cast<VkDeviceSize>(cmd->offset);

                    device->fn.CmdBindVertexBuffers(commands, static_cast<uint8_t>(cmd->slot), 1,
                                                    &*buffer, &offset);
                    break;
                }

                default:
                    UNREACHABLE();
                    break;
            }
        };

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::EndRenderPass: {
                    mCommands.NextCommand<EndRenderPassCmd>();
                    device->fn.CmdEndRenderPass(commands);
                    return {};
                }

                case Command::SetBlendConstant: {
                    SetBlendConstantCmd* cmd = mCommands.NextCommand<SetBlendConstantCmd>();
                    const std::array<float, 4> blendConstants = ConvertToFloatColor(cmd->color);
                    device->fn.CmdSetBlendConstants(commands, blendConstants.data());
                    break;
                }

                case Command::SetStencilReference: {
                    SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
                    device->fn.CmdSetStencilReference(commands, VK_STENCIL_FRONT_AND_BACK,
                                                      cmd->reference);
                    break;
                }

                case Command::SetViewport: {
                    SetViewportCmd* cmd = mCommands.NextCommand<SetViewportCmd>();
                    VkViewport viewport;
                    viewport.x = cmd->x;
                    viewport.y = cmd->y + cmd->height;
                    viewport.width = cmd->width;
                    viewport.height = -cmd->height;
                    viewport.minDepth = cmd->minDepth;
                    viewport.maxDepth = cmd->maxDepth;

                    // Vulkan disallows width = 0, but VK_KHR_maintenance1 which we require allows
                    // height = 0 so use that to do an empty viewport.
                    if (viewport.width == 0) {
                        viewport.height = 0;

                        // Set the viewport x range to a range that's always valid.
                        viewport.x = 0;
                        viewport.width = 1;
                    }

                    device->fn.CmdSetViewport(commands, 0, 1, &viewport);
                    break;
                }

                case Command::SetScissorRect: {
                    SetScissorRectCmd* cmd = mCommands.NextCommand<SetScissorRectCmd>();
                    VkRect2D rect;
                    rect.offset.x = cmd->x;
                    rect.offset.y = cmd->y;
                    rect.extent.width = cmd->width;
                    rect.extent.height = cmd->height;

                    device->fn.CmdSetScissor(commands, 0, 1, &rect);
                    break;
                }

                case Command::ExecuteBundles: {
                    ExecuteBundlesCmd* cmd = mCommands.NextCommand<ExecuteBundlesCmd>();
                    auto bundles = mCommands.NextData<Ref<RenderBundleBase>>(cmd->count);

                    for (uint32_t i = 0; i < cmd->count; ++i) {
                        CommandIterator* iter = bundles[i]->GetCommands();
                        iter->Reset();
                        while (iter->NextCommandId(&type)) {
                            EncodeRenderBundleCommand(iter, type);
                        }
                    }
                    break;
                }

                case Command::BeginOcclusionQuery: {
                    BeginOcclusionQueryCmd* cmd = mCommands.NextCommand<BeginOcclusionQueryCmd>();

                    device->fn.CmdBeginQuery(commands, ToBackend(cmd->querySet.Get())->GetHandle(),
                                             cmd->queryIndex, 0);
                    break;
                }

                case Command::EndOcclusionQuery: {
                    EndOcclusionQueryCmd* cmd = mCommands.NextCommand<EndOcclusionQueryCmd>();

                    device->fn.CmdEndQuery(commands, ToBackend(cmd->querySet.Get())->GetHandle(),
                                           cmd->queryIndex);
                    break;
                }

                case Command::WriteTimestamp: {
                    WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();

                    RecordWriteTimestampCmd(recordingContext, device, cmd);
                    break;
                }

                default: {
                    EncodeRenderBundleCommand(&mCommands, type);
                    break;
                }
            }
        }

        // EndRenderPass should have been called
        UNREACHABLE();
    }

}}  // namespace dawn_native::vulkan
