// 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::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::SetValidatedBufferLocationsInternal:
                    DoNextSetValidatedBufferLocationsInternal();
                    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>();
                    VkBuffer indirectBuffer = ToBackend(draw->indirectBuffer)->GetHandle();

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

                case Command::DrawIndexedIndirect: {
                    DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
                    ASSERT(!draw->indirectBufferLocation->IsNull());
                    VkBuffer indirectBuffer =
                        ToBackend(draw->indirectBufferLocation->GetBuffer())->GetHandle();

                    descriptorSets.Apply(device, recordingContext, VK_PIPELINE_BIND_POINT_GRAPHICS);
                    device->fn.CmdDrawIndexedIndirect(
                        commands, indirectBuffer,
                        static_cast<VkDeviceSize>(draw->indirectBufferLocation->GetOffset()), 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
