// 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::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,
                        attachmentInfo.depthReadOnly || attachmentInfo.stencilReadOnly);
                }

                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
