// 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/DynamicUploader.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/StagingBufferVk.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:
                    break;
            }
            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(crbug.com/dawn/814): 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(crbug.com/dawn/814): 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) {
                BeforeApply();
                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);
                }
                AfterApply();
            }
        };

        // 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;

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

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

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

                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>();
                    if (copy->size == 0) {
                        // Skip no-op copies.
                        break;
                    }

                    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>();
                    if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
                        copy->copySize.depthOrArrayLayers == 0) {
                        // Skip no-op copies.
                        continue;
                    }
                    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>();
                    if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
                        copy->copySize.depthOrArrayLayers == 0) {
                        // Skip no-op copies.
                        continue;
                    }
                    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>();
                    if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
                        copy->copySize.depthOrArrayLayers == 0) {
                        // Skip no-op copies.
                        continue;
                    }
                    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::ClearBuffer: {
                    ClearBufferCmd* cmd = mCommands.NextCommand<ClearBufferCmd>();
                    if (cmd->size == 0) {
                        // Skip no-op fills.
                        break;
                    }

                    Buffer* dstBuffer = ToBackend(cmd->buffer.Get());
                    bool clearedToZero = dstBuffer->EnsureDataInitializedAsDestination(
                        recordingContext, cmd->offset, cmd->size);

                    if (!clearedToZero) {
                        dstBuffer->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopyDst);
                        device->fn.CmdFillBuffer(recordingContext->commandBuffer,
                                                 dstBuffer->GetHandle(), cmd->offset, cmd->size,
                                                 0u);
                    }

                    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());

                    destination->EnsureDataInitializedAsDestination(
                        recordingContext, cmd->destinationOffset,
                        cmd->queryCount * sizeof(uint64_t));

                    // vkCmdCopyQueryPoolResults only can retrieve available queries because
                    // VK_QUERY_RESULT_WAIT_BIT is set. In order to resolve the unavailable queries
                    // as 0s, we need to clear the resolving region of the destination buffer to 0s.
                    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->TransitionUsageNow(recordingContext,
                                                        wgpu::BufferUsage::CopyDst);
                        device->fn.CmdFillBuffer(commands, destination->GetHandle(),
                                                 cmd->destinationOffset,
                                                 cmd->queryCount * sizeof(uint64_t), 0u);
                    }

                    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;
                }

                case Command::WriteBuffer: {
                    WriteBufferCmd* write = mCommands.NextCommand<WriteBufferCmd>();
                    const uint64_t offset = write->offset;
                    const uint64_t size = write->size;
                    if (size == 0) {
                        continue;
                    }

                    Buffer* dstBuffer = ToBackend(write->buffer.Get());
                    uint8_t* data = mCommands.NextData<uint8_t>(size);
                    Device* device = ToBackend(GetDevice());

                    UploadHandle uploadHandle;
                    DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
                                                      size, device->GetPendingCommandSerial(),
                                                      kCopyBufferToBufferOffsetAlignment));
                    ASSERT(uploadHandle.mappedBuffer != nullptr);
                    memcpy(uploadHandle.mappedBuffer, data, size);

                    dstBuffer->EnsureDataInitializedAsDestination(recordingContext, offset, size);

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

                    VkBufferCopy copy;
                    copy.srcOffset = uploadHandle.startOffset;
                    copy.dstOffset = offset;
                    copy.size = size;

                    device->fn.CmdCopyBuffer(
                        commands, ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(),
                        dstBuffer->GetHandle(), 1, &copy);
                    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>();
                    Buffer* buffer = ToBackend(draw->indirectBuffer.Get());

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

                case Command::DrawIndexedIndirect: {
                    DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
                    Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
                    ASSERT(buffer != nullptr);

                    descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_GRAPHICS);
                    device->fn.CmdDrawIndexedIndirect(
                        commands, buffer->GetHandle(),
                        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
