// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "dawn/native/d3d11/CommandBufferD3D11.h"

#include <algorithm>
#include <array>
#include <string>
#include <utility>
#include <vector>

#include "dawn/common/BitSetRangeIterator.h"
#include "dawn/common/WindowsUtils.h"
#include "dawn/native/ApplyClearColorValueWithDrawHelper.h"
#include "dawn/native/ChainUtils.h"
#include "dawn/native/CommandEncoder.h"
#include "dawn/native/CommandValidation.h"
#include "dawn/native/Commands.h"
#include "dawn/native/ExternalTexture.h"
#include "dawn/native/ImmediateConstantsTracker.h"
#include "dawn/native/Queue.h"
#include "dawn/native/RenderBundle.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d11/BindGroupTrackerD3D11.h"
#include "dawn/native/d3d11/BufferD3D11.h"
#include "dawn/native/d3d11/CommandRecordingContextD3D11.h"
#include "dawn/native/d3d11/ComputePipelineD3D11.h"
#include "dawn/native/d3d11/DeviceD3D11.h"
#include "dawn/native/d3d11/Forward.h"
#include "dawn/native/d3d11/PipelineLayoutD3D11.h"
#include "dawn/native/d3d11/PipelineStateTrackerD3D11.h"
#include "dawn/native/d3d11/QuerySetD3D11.h"
#include "dawn/native/d3d11/RenderPipelineD3D11.h"
#include "dawn/native/d3d11/TextureD3D11.h"
#include "dawn/native/d3d11/UtilsD3D11.h"
#include "partition_alloc/pointers/raw_ptr.h"

namespace dawn::native::d3d11 {
namespace {

DXGI_FORMAT DXGIIndexFormat(wgpu::IndexFormat format) {
    switch (format) {
        case wgpu::IndexFormat::Uint16:
            return DXGI_FORMAT_R16_UINT;
        case wgpu::IndexFormat::Uint32:
            return DXGI_FORMAT_R32_UINT;
        default:
            DAWN_UNREACHABLE();
    }
}

class VertexBufferTracker {
  public:
    explicit VertexBufferTracker(const ScopedSwapStateCommandRecordingContext* commandContext)
        : mCommandContext(commandContext) {}

    ~VertexBufferTracker() {
        mD3D11Buffers = {};
        mStrides = {};
        mOffsets = {};
        mCommandContext->GetD3D11DeviceContext3()->IASetVertexBuffers(
            0, kMaxVertexBuffers, mD3D11Buffers.data(), mStrides.data(), mOffsets.data());
    }

    void OnSetVertexBuffer(VertexBufferSlot slot, ID3D11Buffer* buffer, uint64_t offset) {
        if (mD3D11Buffers[slot] == buffer && mOffsets[slot] == offset) {
            return;
        }

        mD3D11Buffers[slot] = buffer;
        mOffsets[slot] = offset;

        mDirtyVertexBuffers.set(slot);
    }

    void Apply(const RenderPipeline* renderPipeline) {
        DAWN_ASSERT(renderPipeline != nullptr);

        // If the vertex state has changed, we need to update the strides.
        if (mLastAppliedRenderPipeline != renderPipeline) {
            mLastAppliedRenderPipeline = renderPipeline;
            for (VertexBufferSlot slot : renderPipeline->GetVertexBuffersUsed()) {
                if (mStrides[slot] == renderPipeline->GetVertexBuffer(slot).arrayStride) {
                    continue;
                }

                mStrides[slot] = renderPipeline->GetVertexBuffer(slot).arrayStride;
                mDirtyVertexBuffers.set(slot);
            }
        }

        const auto vertexBuffersToApply =
            mDirtyVertexBuffers & renderPipeline->GetVertexBuffersUsed();

        for (VertexBufferSlot slot : vertexBuffersToApply) {
            mCommandContext->GetD3D11DeviceContext3()->IASetVertexBuffers(
                uint8_t(slot), 1, &mD3D11Buffers[slot], &mStrides[slot], &mOffsets[slot]);

            mDirtyVertexBuffers.reset(slot);
        }
    }

  private:
    raw_ptr<const ScopedSwapStateCommandRecordingContext> mCommandContext;
    raw_ptr<const RenderPipeline> mLastAppliedRenderPipeline = nullptr;
    PerVertexBuffer<ID3D11Buffer*> mD3D11Buffers = {};
    PerVertexBuffer<UINT> mStrides = {};
    PerVertexBuffer<UINT> mOffsets = {};
    VertexBufferMask mDirtyVertexBuffers;
};

// Handle pixel local storage attachments and return a vector of all pixel local storage UAVs.
// - For implicit attachments, create the texture and clear it to 0.
// - For explicit attachments, clear them to the specified clear color if their load operation is
//   `clear`
ResultOrError<std::vector<ComPtr<ID3D11UnorderedAccessView>>>
HandlePixelLocalStorageAndGetPixelLocalStorageUAVs(
    DeviceBase* device,
    const BeginRenderPassCmd* renderPass,
    const ScopedSwapStateCommandRecordingContext* commandContext) {
    std::vector<ComPtr<ID3D11UnorderedAccessView>> pixelLocalStorageUAVs;
    auto d3d11DeviceContext = commandContext->GetD3D11DeviceContext3();

    const std::vector<wgpu::TextureFormat>& storageAttachmentSlots =
        renderPass->attachmentState->GetStorageAttachmentSlots();
    uint32_t nextImplicitAttachmentIndex = 0;
    for (size_t attachment = 0; attachment < storageAttachmentSlots.size(); attachment++) {
        ComPtr<ID3D11UnorderedAccessView> pixelLocalStorageUAV;
        if (storageAttachmentSlots[attachment] == wgpu::TextureFormat::Undefined) {
            // Get implicit pixel local storage attachment
            TextureViewBase* implicitPixelLocalStorageTextureView = nullptr;
            DAWN_TRY_ASSIGN(
                implicitPixelLocalStorageTextureView,
                ToBackend(device)->GetOrCreateCachedImplicitPixelLocalStorageAttachment(
                    renderPass->width, renderPass->height, nextImplicitAttachmentIndex));
            ++nextImplicitAttachmentIndex;

            // Get and clear the UAV of the implicit pixel local storage attachment
            DAWN_TRY_ASSIGN(pixelLocalStorageUAV, ToBackend(implicitPixelLocalStorageTextureView)
                                                      ->GetOrCreateD3D11UnorderedAccessView());

            // TODO(dawn:1704): investigate if we can only clear it when necessary.
            uint32_t clearValue[4] = {0, 0, 0, 0};
            d3d11DeviceContext->ClearUnorderedAccessViewUint(pixelLocalStorageUAV.Get(),
                                                             clearValue);
        } else {
            // Get the UAV of the explicit pixel local storage attachment
            auto& attachmentInfo = renderPass->storageAttachments[attachment];
            DAWN_TRY_ASSIGN(
                pixelLocalStorageUAV,
                ToBackend(attachmentInfo.storage.Get())->GetOrCreateD3D11UnorderedAccessView());

            // Execute the load operation of the pixel local storage attachment
            switch (attachmentInfo.loadOp) {
                case wgpu::LoadOp::Clear: {
                    switch (attachmentInfo.storage->GetFormat().format) {
                        case wgpu::TextureFormat::R32Float: {
                            float clearValue[4] = {static_cast<float>(attachmentInfo.clearColor.r),
                                                   0, 0, 0};
                            d3d11DeviceContext->ClearUnorderedAccessViewFloat(
                                pixelLocalStorageUAV.Get(), clearValue);
                            break;
                        }
                        case wgpu::TextureFormat::R32Sint: {
                            uint32_t clearValue[4] = {static_cast<uint32_t>(static_cast<int32_t>(
                                                          attachmentInfo.clearColor.r)),
                                                      0, 0, 0};
                            d3d11DeviceContext->ClearUnorderedAccessViewUint(
                                pixelLocalStorageUAV.Get(), clearValue);
                            break;
                        }
                        case wgpu::TextureFormat::R32Uint: {
                            uint32_t clearValue[4] = {
                                static_cast<uint32_t>(attachmentInfo.clearColor.r), 0, 0, 0};
                            d3d11DeviceContext->ClearUnorderedAccessViewUint(
                                pixelLocalStorageUAV.Get(), clearValue);
                            break;
                        }
                        default:
                            DAWN_UNREACHABLE();
                            break;
                    }
                    break;
                }
                case wgpu::LoadOp::Load:
                case wgpu::LoadOp::ExpandResolveTexture:
                    break;
                case wgpu::LoadOp::Undefined:
                    DAWN_UNREACHABLE();
                    break;
            }
        }
        pixelLocalStorageUAVs.push_back(pixelLocalStorageUAV);
    }

    return pixelLocalStorageUAVs;
}

template <typename T>
class ImmediateConstantTracker : public T {
  public:
    ImmediateConstantTracker() = default;

    MaybeError Apply(const ScopedSwapStateCommandRecordingContext* commandContext) {
        DAWN_ASSERT(this->mLastPipeline != nullptr);

        ImmediateConstantMask pipelineMask = this->mLastPipeline->GetImmediateMask();
        ImmediateConstantMask uploadBits = this->mDirty & pipelineMask;
        for (auto&& [offset, size] : IterateRanges(uploadBits)) {
            uint32_t immediateContentStartOffset =
                static_cast<uint32_t>(offset) * kImmediateConstantElementByteSize;
            uint32_t immediateRangeStartOffset =
                GetImmediateIndexInPipeline(static_cast<uint32_t>(offset), pipelineMask);
            commandContext->WriteUniformBufferRange(
                immediateRangeStartOffset,
                this->mContent.template Get<uint32_t>(immediateContentStartOffset),
                size * kImmediateConstantElementByteSize);
        }

        // Reset all dirty bits after uploading.
        this->mDirty.reset();

        return commandContext->FlushUniformBuffer();
    }

    uint32_t GetFirstIndexContentStartOffset() {
        uint32_t startIndex =
            offsetof(RenderImmediateConstants, firstVertex) / kImmediateConstantElementByteSize;
        ImmediateConstantMask prefixBits = ImmediateConstantMask((1u << startIndex) - 1u);
        return (prefixBits & this->mDirty).count() * kImmediateConstantElementByteSize;
    }
};

}  // namespace

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

MaybeError CommandBuffer::Execute(const ScopedSwapStateCommandRecordingContext* commandContext) {
    ExecutionSerial pendingSerial = GetDevice()->GetQueue()->GetPendingCommandSerial();

    auto LazyClearSyncScope = [&commandContext,
                               pendingSerial](const SyncScopeResourceUsage& scope) -> MaybeError {
        for (size_t i = 0; i < scope.textures.size(); i++) {
            Texture* texture = ToBackend(scope.textures[i]);

            // Clear subresources that are not render attachments or storage attachment. 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. Storage
            // attachments will also be cleared in RecordBeginRenderPass by
            // ClearUnorderedAccessView*() when the texture subresource has not been initialized
            // before the render pass.
            DAWN_TRY(scope.textureSyncInfos[i].Iterate([&](const SubresourceRange& range,
                                                           TextureSyncInfo syncInfo) -> MaybeError {
                if (syncInfo.usage & ~(wgpu::TextureUsage::RenderAttachment |
                                       wgpu::TextureUsage::StorageAttachment)) {
                    DAWN_TRY(texture->EnsureSubresourceContentInitialized(commandContext, range));
                }
                return {};
            }));
        }

        for (BufferBase* buffer : scope.buffers) {
            DAWN_TRY(ToBackend(buffer)->TrackUsage(commandContext, pendingSerial));
            DAWN_TRY(ToBackend(buffer)->EnsureDataInitialized(commandContext));
        }

        return {};
    };

    PipelineStateTracker pipelineStateTracker(commandContext);
    PassIndex nextComputePassNumber{0};
    PassIndex nextRenderPassNumber{0};

    Command type;
    while (mCommands.NextCommandId(&type)) {
        switch (type) {
            case Command::BeginComputePass: {
                mCommands.NextCommand<BeginComputePassCmd>();
                for (const SyncScopeResourceUsage& scope :
                     GetResourceUsages().computePasses[nextComputePassNumber].dispatchUsages) {
                    for (TextureBase* texture : scope.textures) {
                        DAWN_TRY(ToBackend(texture)->SynchronizeTextureBeforeUse(commandContext));
                    }
                    DAWN_TRY(LazyClearSyncScope(scope));
                }
                DAWN_TRY(ExecuteComputePass(commandContext, &pipelineStateTracker));

                nextComputePassNumber++;
                break;
            }

            case Command::BeginRenderPass: {
                auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
                for (TextureBase* texture :
                     GetResourceUsages().renderPasses[nextRenderPassNumber].textures) {
                    DAWN_TRY(ToBackend(texture)->SynchronizeTextureBeforeUse(commandContext));
                }
                for (ExternalTextureBase* externalTexture :
                     GetResourceUsages().renderPasses[nextRenderPassNumber].externalTextures) {
                    for (auto& view : externalTexture->GetTextureViews()) {
                        if (view.Get()) {
                            DAWN_TRY(ToBackend(view->GetTexture())
                                         ->SynchronizeTextureBeforeUse(commandContext));
                        }
                    }
                }
                DAWN_TRY(
                    LazyClearSyncScope(GetResourceUsages().renderPasses[nextRenderPassNumber]));
                DAWN_TRY(ExecuteRenderPass(cmd, commandContext, &pipelineStateTracker,
                                           nextRenderPassNumber));

                nextRenderPassNumber++;
                break;
            }

            case Command::CopyBufferToBuffer: {
                CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
                if (copy->size == 0) {
                    // Skip no-op copies.
                    break;
                }

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

                DAWN_TRY(source->TrackUsage(commandContext, pendingSerial));
                DAWN_TRY(destination->TrackUsage(commandContext, pendingSerial));

                // Buffer::Copy() will ensure the source and destination buffers are initialized.
                DAWN_TRY(Buffer::Copy(commandContext, source, copy->sourceOffset, copy->size,
                                      destination, copy->destinationOffset));
                break;
            }

            case Command::CopyBufferToTexture: {
                CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                if (copy->copySize.IsEmpty()) {
                    // Skip no-op copies.
                    continue;
                }

                auto& src = copy->source;
                auto& dst = copy->destination;

                Buffer* buffer = ToBackend(src.buffer.Get());
                DAWN_TRY(buffer->TrackUsage(commandContext, pendingSerial));

                uint64_t bufferOffset = src.offset;
                Ref<BufferBase> stagingBuffer;
                const TypedTexelBlockInfo& blockInfo = GetBlockInfo(dst);

                // If the buffer is not mappable, we need to create a staging buffer and copy the
                // data from the buffer to the staging buffer.
                std::optional<BufferBase::ScopedUseBuffer> use;
                if (!buffer->IsCPUReadable()) {
                    // TODO(dawn:1768): use compute shader to copy data from buffer to texture.
                    BufferDescriptor desc;
                    desc.size =
                        ComputeRequiredBytesInCopy(blockInfo, blockInfo.ToBlock(copy->copySize),
                                                   src.blocksPerRow, src.rowsPerImage);
                    desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
                    DAWN_TRY_ASSIGN(stagingBuffer, Buffer::Create(ToBackend(GetDevice()),
                                                                  Unpack(&desc), commandContext));
                    use = stagingBuffer->UseInternal();
                    DAWN_TRY(Buffer::Copy(commandContext, buffer, src.offset,
                                          stagingBuffer->GetSize(), ToBackend(stagingBuffer.Get()),
                                          0));
                    buffer = ToBackend(stagingBuffer.Get());
                    bufferOffset = 0;
                }

                Buffer::ScopedMap scopedMap;
                DAWN_TRY_ASSIGN(scopedMap, Buffer::ScopedMap::Create(commandContext, buffer,
                                                                     wgpu::MapMode::Read));
                DAWN_TRY(buffer->EnsureDataInitialized(commandContext));

                Texture* texture = ToBackend(dst.texture.Get());
                DAWN_TRY(texture->SynchronizeTextureBeforeUse(commandContext));
                SubresourceRange subresources = GetSubresourcesAffectedByCopy(dst, copy->copySize);

                DAWN_ASSERT(scopedMap.GetMappedData());
                const uint8_t* data = scopedMap.GetMappedData() + bufferOffset;
                uint64_t bytesPerRow = blockInfo.ToBytes(src.blocksPerRow);
                DAWN_TRY(texture->Write(commandContext, subresources, dst.origin.ToOrigin3D(),
                                        copy->copySize.ToExtent3D(), data,
                                        static_cast<uint32_t>(bytesPerRow),
                                        static_cast<uint32_t>(src.rowsPerImage)));
                break;
            }

            case Command::CopyTextureToBuffer: {
                CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                if (copy->copySize.IsEmpty()) {
                    // Skip no-op copies.
                    continue;
                }

                auto& src = copy->source;
                auto& dst = copy->destination;

                Buffer* buffer = ToBackend(dst.buffer.Get());
                DAWN_TRY(buffer->TrackUsage(commandContext, pendingSerial));

                SubresourceRange subresources = GetSubresourcesAffectedByCopy(src, copy->copySize);
                Texture* texture = ToBackend(src.texture.Get());
                DAWN_TRY(texture->SynchronizeTextureBeforeUse(commandContext));
                DAWN_TRY(
                    texture->EnsureSubresourceContentInitialized(commandContext, subresources));

                Buffer::ScopedMap scopedDstMap;
                DAWN_TRY_ASSIGN(scopedDstMap, Buffer::ScopedMap::Create(commandContext, buffer,
                                                                        wgpu::MapMode::Write));

                DAWN_TRY(buffer->EnsureDataInitializedAsDestination(commandContext, copy));

                Texture::ReadCallback callback = [&](const uint8_t* data, uint64_t offset,
                                                     uint64_t size) -> MaybeError {
                    DAWN_TRY(ToBackend(dst.buffer)
                                 ->Write(commandContext, dst.offset + offset, data, size));
                    return {};
                };

                const TypedTexelBlockInfo& blockInfo = GetBlockInfo(src);
                uint64_t bytesPerRow = blockInfo.ToBytes(dst.blocksPerRow);

                DAWN_TRY(ToBackend(src.texture)
                             ->Read(commandContext, subresources, src.origin.ToOrigin3D(),
                                    copy->copySize.ToExtent3D(), static_cast<uint32_t>(bytesPerRow),
                                    static_cast<uint32_t>(dst.rowsPerImage), callback));
                break;
            }

            case Command::CopyTextureToTexture: {
                CopyTextureToTextureCmd* copy = mCommands.NextCommand<CopyTextureToTextureCmd>();
                if (copy->copySize.IsEmpty()) {
                    // Skip no-op copies.
                    continue;
                }

                DAWN_TRY(ToBackend(copy->source.texture.Get())
                             ->SynchronizeTextureBeforeUse(commandContext));
                DAWN_TRY(ToBackend(copy->destination.texture.Get())
                             ->SynchronizeTextureBeforeUse(commandContext));
                DAWN_TRY(Texture::Copy(commandContext, copy));
                break;
            }

            case Command::ClearBuffer: {
                ClearBufferCmd* cmd = mCommands.NextCommand<ClearBufferCmd>();
                if (cmd->size == 0) {
                    // Skip no-op fills.
                    break;
                }
                Buffer* buffer = ToBackend(cmd->buffer.Get());
                DAWN_TRY(buffer->TrackUsage(commandContext, pendingSerial));
                DAWN_TRY(buffer->Clear(commandContext, 0, cmd->offset, cmd->size));
                break;
            }

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

                DAWN_TRY(destination->TrackUsage(commandContext, pendingSerial));
                DAWN_TRY(querySet->Resolve(commandContext, cmd->firstQuery, cmd->queryCount,
                                           destination, cmd->destinationOffset));
                break;
            }

            case Command::WriteTimestamp: {
                return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");
            }

            case Command::WriteBuffer: {
                WriteBufferCmd* cmd = mCommands.NextCommand<WriteBufferCmd>();
                uint8_t* data = mCommands.NextData<uint8_t>(cmd->size);

                if (cmd->size == 0) {
                    // Skip no-op writes.
                    continue;
                }

                Buffer* dstBuffer = ToBackend(cmd->buffer.Get());
                DAWN_TRY(dstBuffer->TrackUsage(commandContext, pendingSerial));
                DAWN_TRY(dstBuffer->Write(commandContext, cmd->offset, data, cmd->size));

                break;
            }

            case Command::InsertDebugMarker:
            case Command::PopDebugGroup:
            case Command::PushDebugGroup: {
                HandleDebugCommands(commandContext, &mCommands, type);
                break;
            }

            default:
                return DAWN_FORMAT_INTERNAL_ERROR("Unknown command type: %d", type);
        }
    }

    return {};
}

MaybeError CommandBuffer::ExecuteComputePass(
    const ScopedSwapStateCommandRecordingContext* commandContext,
    PipelineStateTracker* pipelineStateTracker) {
    ComputePipeline* lastPipeline = nullptr;
    ComputePassBindGroupTracker bindGroupTracker(commandContext);

    ImmediateConstantTracker<ComputeImmediateConstantsTrackerBase> immediates = {};

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

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

                DAWN_TRY(bindGroupTracker.Apply());
                immediates.SetNumWorkgroups(dispatch->x, dispatch->y, dispatch->z);
                DAWN_TRY(immediates.Apply(commandContext));
                commandContext->GetD3D11DeviceContext3()->Dispatch(dispatch->x, dispatch->y,
                                                                   dispatch->z);

                break;
            }

            case Command::DispatchIndirect: {
                DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>();

                DAWN_TRY(bindGroupTracker.Apply());
                auto* indirectBuffer = ToGPUUsableBuffer(dispatch->indirectBuffer.Get());
                DAWN_TRY(immediates.Apply(commandContext));

                if (lastPipeline->UsesNumWorkgroups()) {
                    // Copy indirect args into the uniform buffer for built-in workgroup variables.
                    DAWN_TRY(Buffer::Copy(commandContext, indirectBuffer, dispatch->indirectOffset,
                                          sizeof(uint32_t) * 3,
                                          commandContext->GetInternalUniformBuffer(), 0));
                }

                ID3D11Buffer* d3dBuffer;
                DAWN_TRY_ASSIGN(d3dBuffer,
                                indirectBuffer->GetD3D11NonConstantBuffer(commandContext));
                commandContext->GetD3D11DeviceContext3()->DispatchIndirect(
                    d3dBuffer, dispatch->indirectOffset);
                break;
            }

            case Command::SetComputePipeline: {
                SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
                lastPipeline = ToBackend(cmd->pipeline).Get();
                lastPipeline->ApplyNow(pipelineStateTracker);
                bindGroupTracker.OnSetPipeline(lastPipeline);
                immediates.OnSetPipeline(lastPipeline);
                break;
            }

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

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

                bindGroupTracker.OnSetBindGroup(cmd->index, cmd->group.Get(),
                                                cmd->dynamicOffsetCount, dynamicOffsets);

                break;
            }

            case Command::WriteTimestamp: {
                return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");
            }

            case Command::InsertDebugMarker:
            case Command::PopDebugGroup:
            case Command::PushDebugGroup: {
                HandleDebugCommands(commandContext, &mCommands, type);
                break;
            }

            case Command::SetImmediates: {
                SetImmediatesCmd* cmd = mCommands.NextCommand<SetImmediatesCmd>();
                DAWN_ASSERT(cmd->size > 0);
                uint8_t* value = mCommands.NextData<uint8_t>(cmd->size);
                immediates.SetImmediates(cmd->offset, value, cmd->size);
                break;
            }

            default:
                DAWN_UNREACHABLE();
        }
    }

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

MaybeError CommandBuffer::ExecuteRenderPass(
    BeginRenderPassCmd* renderPass,
    const ScopedSwapStateCommandRecordingContext* commandContext,
    PipelineStateTracker* pipelineStateTracker,
    PassIndex renderPassIndex) {
    const IndirectDrawMetadata& metadata = GetIndirectDrawMetadata()[renderPassIndex];
    IndirectDrawIndex indirectDrawIndex{0};

    // For the color attachments that the clear_color_with_draw workaround has applied, we can skip
    // the clear for them.
    for (auto i : ClearWithDrawHelper::GetAppliedColorAttachments(GetDevice(), renderPass)) {
        auto& colorAttachment = renderPass->colorAttachments[i];
        DAWN_ASSERT(colorAttachment.loadOp == wgpu::LoadOp::Clear);
        // Skip the clear as it will be handled by the workaround.
        colorAttachment.loadOp = wgpu::LoadOp::Load;
        // Mark the resource as initialized to avoid the lazy clear.
        // For 3D textures, the view range covers the entire mip level (all depth slices), but
        // the workaround only clears a single slice. So we must not mark it as initialized
        // here, and let LazyClearRenderPassAttachments handle the initialization of the
        // other slices.
        if (colorAttachment.view->GetTexture()->GetDimension() != wgpu::TextureDimension::e3D) {
            SubresourceRange range = colorAttachment.view->GetSubresourceRange();
            colorAttachment.view->GetTexture()->SetIsSubresourceContentInitialized(true, range);
        }
    }
    DAWN_TRY(LazyClearRenderPassAttachments(
        GetDevice(), renderPass, [&](TextureBase* texture, const SubresourceRange& range) {
            return ToBackend(texture)->EnsureSubresourceContentInitialized(commandContext, range);
        }));

    auto* d3d11DeviceContext = commandContext->GetD3D11DeviceContext3();
    // Hold ID3D11RenderTargetView ComPtr to make attachments alive.
    PerColorAttachment<ID3D11RenderTargetView*> d3d11RenderTargetViews = {};
    ColorAttachmentIndex attachmentCount{};
    // TODO(dawn:1815): Shrink the sparse attachments to accommodate more UAVs.
    for (auto i : renderPass->attachmentState->GetColorAttachmentsMask()) {
        TextureView* colorTextureView = ToBackend(renderPass->colorAttachments[i].view.Get());
        DAWN_TRY_ASSIGN(d3d11RenderTargetViews[i],
                        colorTextureView->GetOrCreateD3D11RenderTargetView(
                            renderPass->colorAttachments[i].depthSlice));
        if (renderPass->colorAttachments[i].loadOp == wgpu::LoadOp::Clear) {
            std::array<float, 4> clearColor =
                ConvertToFloatColor(renderPass->colorAttachments[i].clearColor);
            d3d11DeviceContext->ClearRenderTargetView(d3d11RenderTargetViews[i], clearColor.data());
        }
        attachmentCount = ityp::PlusOne(i);
    }

    ID3D11DepthStencilView* d3d11DepthStencilView = nullptr;
    if (renderPass->attachmentState->HasDepthStencilAttachment()) {
        auto* attachmentInfo = &renderPass->depthStencilAttachment;
        const Format& attachmentFormat = attachmentInfo->view->GetTexture()->GetFormat();

        TextureView* depthStencilTextureView =
            ToBackend(renderPass->depthStencilAttachment.view.Get());
        DAWN_TRY_ASSIGN(d3d11DepthStencilView,
                        depthStencilTextureView->GetOrCreateD3D11DepthStencilView(
                            attachmentInfo->depthReadOnly, attachmentInfo->stencilReadOnly));
        UINT clearFlags = 0;
        if (attachmentFormat.HasDepth() &&
            renderPass->depthStencilAttachment.depthLoadOp == wgpu::LoadOp::Clear) {
            clearFlags |= D3D11_CLEAR_DEPTH;
        }

        if (attachmentFormat.HasStencil() &&
            renderPass->depthStencilAttachment.stencilLoadOp == wgpu::LoadOp::Clear) {
            clearFlags |= D3D11_CLEAR_STENCIL;
        }

        d3d11DeviceContext->ClearDepthStencilView(d3d11DepthStencilView, clearFlags,
                                                  attachmentInfo->clearDepth,
                                                  attachmentInfo->clearStencil);
    }

    d3d11DeviceContext->OMSetRenderTargets(static_cast<uint8_t>(attachmentCount),
                                           d3d11RenderTargetViews.data(), d3d11DepthStencilView);

    std::vector<ComPtr<ID3D11UnorderedAccessView>> pixelLocalStorageUAVs;
    if (renderPass->attachmentState->HasPixelLocalStorage()) {
        DAWN_TRY_ASSIGN(pixelLocalStorageUAVs, HandlePixelLocalStorageAndGetPixelLocalStorageUAVs(
                                                   GetDevice(), renderPass, commandContext));
    }

    // Set viewport
    D3D11_VIEWPORT defautViewport;
    defautViewport.TopLeftX = 0;
    defautViewport.TopLeftY = 0;
    defautViewport.Width = renderPass->width;
    defautViewport.Height = renderPass->height;
    defautViewport.MinDepth = 0.0f;
    defautViewport.MaxDepth = 1.0f;
    d3d11DeviceContext->RSSetViewports(1, &defautViewport);

    // Set scissor
    D3D11_RECT scissor;
    scissor.left = 0;
    scissor.top = 0;
    scissor.right = renderPass->width;
    scissor.bottom = renderPass->height;
    d3d11DeviceContext->RSSetScissorRects(1, &scissor);

    RenderPipeline* lastPipeline = nullptr;
    RenderPassBindGroupTracker bindGroupTracker(commandContext, std::move(pixelLocalStorageUAVs));
    VertexBufferTracker vertexBufferTracker(commandContext);
    std::array<float, 4> blendColor = {0.0f, 0.0f, 0.0f, 0.0f};
    uint32_t stencilReference = 0;

    ImmediateConstantTracker<RenderImmediateConstantsTrackerBase> immediates = {};

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

                DAWN_TRY(bindGroupTracker.Apply());
                vertexBufferTracker.Apply(lastPipeline);
                immediates.SetFirstIndexOffset(draw->firstVertex, draw->firstInstance);
                DAWN_TRY(immediates.Apply(commandContext));
                commandContext->GetD3D11DeviceContext3()->DrawInstanced(
                    draw->vertexCount, draw->instanceCount, draw->firstVertex, draw->firstInstance);

                break;
            }

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

                DAWN_TRY(bindGroupTracker.Apply());
                vertexBufferTracker.Apply(lastPipeline);
                immediates.SetFirstIndexOffset(draw->baseVertex, draw->firstInstance);
                DAWN_TRY(immediates.Apply(commandContext));
                commandContext->GetD3D11DeviceContext3()->DrawIndexedInstanced(
                    draw->indexCount, draw->instanceCount, draw->firstIndex, draw->baseVertex,
                    draw->firstInstance);

                break;
            }

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

                IndirectDrawMetadata::ValidatedIndirectDraw validatedDraw =
                    metadata.GetValidatedIndirectDraw(draw, indirectDrawIndex++);

                auto* indirectBuffer = ToGPUUsableBuffer(validatedDraw.indirectBuffer.Get());
                DAWN_ASSERT(indirectBuffer != nullptr);

                DAWN_TRY(bindGroupTracker.Apply());
                vertexBufferTracker.Apply(lastPipeline);
                DAWN_TRY(immediates.Apply(commandContext));

                if (lastPipeline->UsesVertexIndex() || lastPipeline->UsesInstanceIndex()) {
                    // Copy StartVertexLocation and StartInstanceLocation into the uniform buffer
                    // for built-in variables.
                    uint64_t offset =
                        validatedDraw.indirectOffset +
                        offsetof(D3D11_DRAW_INSTANCED_INDIRECT_ARGS, StartVertexLocation);
                    DAWN_TRY(Buffer::Copy(commandContext, indirectBuffer, offset,
                                          sizeof(uint32_t) * 2,
                                          commandContext->GetInternalUniformBuffer(),
                                          immediates.GetFirstIndexContentStartOffset()));
                }

                ID3D11Buffer* d3dBuffer;
                DAWN_TRY_ASSIGN(d3dBuffer,
                                indirectBuffer->GetD3D11NonConstantBuffer(commandContext));
                commandContext->GetD3D11DeviceContext3()->DrawInstancedIndirect(
                    d3dBuffer, validatedDraw.indirectOffset);

                break;
            }

            case Command::DrawIndexedIndirect: {
                DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();

                IndirectDrawMetadata::ValidatedIndirectDraw validatedDraw =
                    metadata.GetValidatedIndirectDraw(draw, indirectDrawIndex++);

                auto* indirectBuffer = ToGPUUsableBuffer(validatedDraw.indirectBuffer.Get());
                DAWN_ASSERT(indirectBuffer != nullptr);

                DAWN_TRY(bindGroupTracker.Apply());
                vertexBufferTracker.Apply(lastPipeline);
                DAWN_TRY(immediates.Apply(commandContext));

                if (lastPipeline->UsesVertexIndex() || lastPipeline->UsesInstanceIndex()) {
                    // Copy StartVertexLocation and StartInstanceLocation into the uniform buffer
                    // for built-in variables.
                    uint64_t offset =
                        validatedDraw.indirectOffset +
                        offsetof(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS, BaseVertexLocation);
                    DAWN_TRY(Buffer::Copy(commandContext, indirectBuffer, offset,
                                          sizeof(uint32_t) * 2,
                                          commandContext->GetInternalUniformBuffer(),
                                          immediates.GetFirstIndexContentStartOffset()));
                }

                ID3D11Buffer* d3dBuffer;
                DAWN_TRY_ASSIGN(d3dBuffer,
                                indirectBuffer->GetD3D11NonConstantBuffer(commandContext));
                commandContext->GetD3D11DeviceContext3()->DrawIndexedInstancedIndirect(
                    d3dBuffer, validatedDraw.indirectOffset);

                break;
            }

            case Command::SetRenderPipeline: {
                SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();

                lastPipeline = ToBackend(cmd->pipeline.Get());
                lastPipeline->ApplyNow(pipelineStateTracker, blendColor, stencilReference);
                bindGroupTracker.OnSetPipeline(lastPipeline);
                immediates.OnSetPipeline(lastPipeline);

                break;
            }

            case Command::SetBindGroup: {
                SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();

                uint32_t* dynamicOffsets = nullptr;
                if (cmd->dynamicOffsetCount > 0) {
                    dynamicOffsets = iter->NextData<uint32_t>(cmd->dynamicOffsetCount);
                }
                bindGroupTracker.OnSetBindGroup(cmd->index, cmd->group.Get(),
                                                cmd->dynamicOffsetCount, dynamicOffsets);

                break;
            }

            case Command::SetIndexBuffer: {
                SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();

                UINT indexBufferBaseOffset = cmd->offset;
                DXGI_FORMAT indexBufferFormat = DXGIIndexFormat(cmd->format);

                ID3D11Buffer* d3dBuffer;
                DAWN_TRY_ASSIGN(d3dBuffer, ToGPUUsableBuffer(cmd->buffer.Get())
                                               ->GetD3D11NonConstantBuffer(commandContext));
                commandContext->GetD3D11DeviceContext3()->IASetIndexBuffer(
                    d3dBuffer, indexBufferFormat, indexBufferBaseOffset);

                break;
            }

            case Command::SetVertexBuffer: {
                SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();
                ID3D11Buffer* d3dBuffer;
                DAWN_TRY_ASSIGN(d3dBuffer, ToGPUUsableBuffer(cmd->buffer.Get())
                                               ->GetD3D11NonConstantBuffer(commandContext));
                vertexBufferTracker.OnSetVertexBuffer(cmd->slot, d3dBuffer, cmd->offset);
                break;
            }

            case Command::InsertDebugMarker:
            case Command::PopDebugGroup:
            case Command::PushDebugGroup: {
                HandleDebugCommands(commandContext, iter, type);
                break;
            }

            case Command::SetImmediates: {
                SetImmediatesCmd* cmd = iter->NextCommand<SetImmediatesCmd>();
                DAWN_ASSERT(cmd->size > 0);
                uint8_t* value = iter->NextData<uint8_t>(cmd->size);
                immediates.SetImmediates(cmd->offset, value, cmd->size);
                break;
            }

            default:
                DAWN_UNREACHABLE();
                break;
        }

        return {};
    };

    Command type;
    while (mCommands.NextCommandId(&type)) {
        switch (type) {
            case Command::EndRenderPass: {
                mCommands.NextCommand<EndRenderPassCmd>();

                if (renderPass->attachmentState->GetSampleCount() > 1) {
                    // Resolve multisampled textures.
                    for (auto i : renderPass->attachmentState->GetColorAttachmentsMask()) {
                        const auto& attachment = renderPass->colorAttachments[i];
                        if (!attachment.resolveTarget.Get()) {
                            continue;
                        }

                        DAWN_ASSERT(attachment.view->GetAspects() == Aspect::Color);
                        DAWN_ASSERT(attachment.resolveTarget->GetAspects() == Aspect::Color);

                        Texture* resolveTexture = ToBackend(attachment.resolveTarget->GetTexture());
                        Texture* colorTexture = ToBackend(attachment.view->GetTexture());
                        uint32_t dstSubresource = resolveTexture->GetSubresourceIndex(
                            attachment.resolveTarget->GetBaseMipLevel(),
                            attachment.resolveTarget->GetBaseArrayLayer(), Aspect::Color);
                        uint32_t srcSubresource = colorTexture->GetSubresourceIndex(
                            attachment.view->GetBaseMipLevel(),
                            attachment.view->GetBaseArrayLayer(), Aspect::Color);
                        d3d11DeviceContext->ResolveSubresource(
                            resolveTexture->GetD3D11Resource(), dstSubresource,
                            colorTexture->GetD3D11Resource(), srcSubresource,
                            d3d::DXGITextureFormat(GetDevice(),
                                                   attachment.resolveTarget->GetFormat().format));
                    }
                }

                if (GetDevice()->IsToggleEnabled(Toggle::D3D11UseDiscardView)) {
                    // Discard render pass' attachments having StoreOp::Discard.
                    for (auto i : renderPass->attachmentState->GetColorAttachmentsMask()) {
                        if (renderPass->colorAttachments[i].storeOp == wgpu::StoreOp::Discard) {
                            d3d11DeviceContext->DiscardView(d3d11RenderTargetViews[i]);
                        }
                    }

                    if (renderPass->attachmentState->HasDepthStencilAttachment()) {
                        auto* attachmentInfo = &renderPass->depthStencilAttachment;
                        const Format& attachmentFormat =
                            attachmentInfo->view->GetTexture()->GetFormat();
                        bool discardDepth = !attachmentFormat.HasDepth() ||
                                            attachmentInfo->depthStoreOp == wgpu::StoreOp::Discard;
                        bool discardStencil =
                            !attachmentFormat.HasStencil() ||
                            attachmentInfo->stencilStoreOp == wgpu::StoreOp::Discard;
                        if (discardDepth && discardStencil) {
                            d3d11DeviceContext->DiscardView(d3d11DepthStencilView);
                        }
                    }
                }

                // Unbind attachments.
                d3d11DeviceContext->OMSetRenderTargets(0, nullptr, nullptr);

                return {};
            }

            case Command::SetStencilReference: {
                SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
                stencilReference = cmd->reference;
                if (lastPipeline) {
                    lastPipeline->ApplyDepthStencilState(pipelineStateTracker, stencilReference);
                }
                break;
            }

            case Command::SetViewport: {
                SetViewportCmd* cmd = mCommands.NextCommand<SetViewportCmd>();

                D3D11_VIEWPORT viewport;
                viewport.TopLeftX = cmd->x;
                viewport.TopLeftY = cmd->y;
                viewport.Width = cmd->width;
                viewport.Height = cmd->height;
                viewport.MinDepth = cmd->minDepth;
                viewport.MaxDepth = cmd->maxDepth;
                commandContext->GetD3D11DeviceContext3()->RSSetViewports(1, &viewport);
                break;
            }

            case Command::SetScissorRect: {
                SetScissorRectCmd* cmd = mCommands.NextCommand<SetScissorRectCmd>();

                D3D11_RECT scissorRect = {static_cast<LONG>(cmd->x), static_cast<LONG>(cmd->y),
                                          static_cast<LONG>(cmd->x + cmd->width),
                                          static_cast<LONG>(cmd->y + cmd->height)};
                commandContext->GetD3D11DeviceContext3()->RSSetScissorRects(1, &scissorRect);
                break;
            }

            case Command::SetBlendConstant: {
                SetBlendConstantCmd* cmd = mCommands.NextCommand<SetBlendConstantCmd>();
                blendColor = ConvertToFloatColor(cmd->color);
                if (lastPipeline) {
                    lastPipeline->ApplyBlendState(pipelineStateTracker, blendColor);
                }
                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)) {
                        DAWN_TRY(DoRenderBundleCommand(iter, type));
                    }
                }
                break;
            }

            case Command::BeginOcclusionQuery: {
                BeginOcclusionQueryCmd* cmd = mCommands.NextCommand<BeginOcclusionQueryCmd>();
                QuerySet* querySet = ToBackend(cmd->querySet.Get());
                querySet->BeginQuery(commandContext->GetD3D11DeviceContext3(), cmd->queryIndex);
                break;
            }

            case Command::EndOcclusionQuery: {
                EndOcclusionQueryCmd* cmd = mCommands.NextCommand<EndOcclusionQueryCmd>();
                QuerySet* querySet = ToBackend(cmd->querySet.Get());
                querySet->EndQuery(commandContext->GetD3D11DeviceContext3(), cmd->queryIndex);
                UpdateQueryAvailability(cmd);
                break;
            }

            case Command::WriteTimestamp:
                return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");

            default: {
                DAWN_TRY(DoRenderBundleCommand(&mCommands, type));
            }
        }
    }

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

void CommandBuffer::HandleDebugCommands(
    const ScopedSwapStateCommandRecordingContext* commandContext,
    CommandIterator* iter,
    Command command) {
    switch (command) {
        case Command::InsertDebugMarker: {
            InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
            std::wstring label = UTF8ToWStr(iter->NextData<char>(cmd->length + 1));
            commandContext->GetD3DUserDefinedAnnotation()->SetMarker(label.c_str());
            break;
        }

        case Command::PopDebugGroup: {
            [[maybe_unused]] auto cmd = iter->NextCommand<PopDebugGroupCmd>();
            commandContext->GetD3DUserDefinedAnnotation()->EndEvent();
            break;
        }

        case Command::PushDebugGroup: {
            PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
            std::wstring label = UTF8ToWStr(iter->NextData<char>(cmd->length + 1));
            commandContext->GetD3DUserDefinedAnnotation()->BeginEvent(label.c_str());
            break;
        }
        default:
            DAWN_UNREACHABLE();
    }
}

}  // namespace dawn::native::d3d11
