// Copyright 2023 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/d3d11/CommandBufferD3D11.h"

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

#include "dawn/common/WindowsUtils.h"
#include "dawn/native/CommandEncoder.h"
#include "dawn/native/CommandValidation.h"
#include "dawn/native/Commands.h"
#include "dawn/native/ExternalTexture.h"
#include "dawn/native/RenderBundle.h"
#include "dawn/native/VertexFormat.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d11/BindGroupTrackerD3D11.h"
#include "dawn/native/d3d11/BufferD3D11.h"
#include "dawn/native/d3d11/ComputePipelineD3D11.h"
#include "dawn/native/d3d11/DeviceD3D11.h"
#include "dawn/native/d3d11/Forward.h"
#include "dawn/native/d3d11/RenderPipelineD3D11.h"
#include "dawn/native/d3d11/TextureD3D11.h"
#include "dawn/native/d3d11/UtilsD3D11.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:
            UNREACHABLE();
    }
}

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

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

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

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

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

        mCommandContext->GetD3D11DeviceContext()->IASetVertexBuffers(
            0, kMaxVertexBuffers, mD3D11Buffers.data(), mStrides.data(), mOffsets.data());
    }

  private:
    CommandRecordingContext* const mCommandContext;
    const RenderPipeline* mLastAppliedRenderPipeline = nullptr;
    ityp::array<VertexBufferSlot, ID3D11Buffer*, kMaxVertexBuffers> mD3D11Buffers = {};
    ityp::array<VertexBufferSlot, UINT, kMaxVertexBuffers> mStrides = {};
    ityp::array<VertexBufferSlot, UINT, kMaxVertexBuffers> mOffsets = {};
};

}  // namespace

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

MaybeError CommandBuffer::Execute() {
    CommandRecordingContext* commandContext = ToBackend(GetDevice())->GetPendingCommandContext();

    auto LazyClearSyncScope = [commandContext](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. 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.
            DAWN_TRY(scope.textureUsages[i].Iterate([&](const SubresourceRange& range,
                                                        wgpu::TextureUsage usage) -> MaybeError {
                if (usage & ~wgpu::TextureUsage::RenderAttachment) {
                    DAWN_TRY(texture->EnsureSubresourceContentInitialized(commandContext, range));
                }
                return {};
            }));
        }

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

        return {};
    };

    size_t nextComputePassNumber = 0;
    size_t nextRenderPassNumber = 0;

    Command type;
    while (mCommands.NextCommandId(&type)) {
        switch (type) {
            case Command::BeginComputePass: {
                mCommands.NextCommand<BeginComputePassCmd>();
                for (const SyncScopeResourceUsage& scope :
                     GetResourceUsages().computePasses[nextComputePassNumber].dispatchUsages) {
                    DAWN_TRY(LazyClearSyncScope(scope));
                }
                DAWN_TRY(ExecuteComputePass(commandContext));

                nextComputePassNumber++;
                break;
            }

            case Command::BeginRenderPass: {
                auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
                DAWN_TRY(
                    LazyClearSyncScope(GetResourceUsages().renderPasses[nextRenderPassNumber]));
                LazyClearRenderPassAttachments(cmd);
                DAWN_TRY(ExecuteRenderPass(cmd, commandContext));

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

                // Buffer::Copy() will ensure the source and destination buffers are initialized.
                DAWN_TRY(Buffer::Copy(commandContext, source, copy->sourceOffset, copy->size,
                                      destination, copy->destinationOffset));
                source->MarkUsedInPendingCommands();
                destination->MarkUsedInPendingCommands();
                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;

                Buffer* buffer = ToBackend(src.buffer.Get());
                uint64_t bufferOffset = src.offset;
                Ref<BufferBase> stagingBuffer;
                // If the buffer is not mappable, we need to create a staging buffer and copy the
                // data from the buffer to the staging buffer.
                if (!(buffer->GetUsage() & kMappableBufferUsages)) {
                    const TexelBlockInfo& blockInfo =
                        ToBackend(dst.texture)->GetFormat().GetAspectInfo(dst.aspect).block;
                    // TODO(dawn:1768): use compute shader to copy data from buffer to texture.
                    BufferDescriptor desc;
                    DAWN_TRY_ASSIGN(desc.size,
                                    ComputeRequiredBytesInCopy(blockInfo, copy->copySize,
                                                               src.bytesPerRow, src.rowsPerImage));
                    desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
                    DAWN_TRY_ASSIGN(stagingBuffer, GetDevice()->CreateBuffer(&desc));

                    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(buffer));
                DAWN_TRY(buffer->EnsureDataInitialized(commandContext));

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

                DAWN_ASSERT(scopedMap.GetMappedData());
                const uint8_t* data = scopedMap.GetMappedData() + bufferOffset;
                DAWN_TRY(texture->Write(commandContext, subresources, dst.origin, copy->copySize,
                                        data, src.bytesPerRow, src.rowsPerImage));

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

                SubresourceRange subresources = GetSubresourcesAffectedByCopy(src, copy->copySize);

                Buffer* buffer = ToBackend(dst.buffer.Get());
                Buffer::ScopedMap scopedDstMap;
                DAWN_TRY_ASSIGN(scopedDstMap, Buffer::ScopedMap::Create(buffer));

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

                DAWN_TRY(ToBackend(src.texture)
                             ->Read(commandContext, subresources, src.origin, copy->copySize,
                                    dst.bytesPerRow, dst.rowsPerImage, callback));

                dst.buffer->MarkUsedInPendingCommands();
                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;
                }

                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->Clear(commandContext, 0, cmd->offset, cmd->size));
                buffer->MarkUsedInPendingCommands();
                break;
            }

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

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

            case Command::WriteBuffer: {
                WriteBufferCmd* cmd = mCommands.NextCommand<WriteBufferCmd>();
                if (cmd->size == 0) {
                    // Skip no-op writes.
                    continue;
                }

                Buffer* dstBuffer = ToBackend(cmd->buffer.Get());
                uint8_t* data = mCommands.NextData<uint8_t>(cmd->size);
                DAWN_TRY(dstBuffer->Write(commandContext, cmd->offset, data, cmd->size));
                dstBuffer->MarkUsedInPendingCommands();

                break;
            }

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

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

    return {};
}

MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandContext) {
    ComputePipeline* lastPipeline = nullptr;
    BindGroupTracker bindGroupTracker(commandContext);

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

                DAWN_TRY(RecordNumWorkgroupsForDispatch(lastPipeline, commandContext, dispatch));
                commandContext->GetD3D11DeviceContext()->Dispatch(dispatch->x, dispatch->y,
                                                                  dispatch->z);

                break;
            }

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

                DAWN_TRY(bindGroupTracker.Apply());

                Buffer* indirectBuffer = ToBackend(dispatch->indirectBuffer.Get());

                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->GetUniformBuffer(),
                                          0));
                }

                commandContext->GetD3D11DeviceContext()->DispatchIndirect(
                    indirectBuffer->GetD3D11NonConstantBuffer(), dispatch->indirectOffset);

                break;
            }

            case Command::SetComputePipeline: {
                SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
                lastPipeline = ToBackend(cmd->pipeline).Get();
                lastPipeline->ApplyNow(commandContext);
                bindGroupTracker.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, type);
                break;
            }

            default:
                UNREACHABLE();
        }
    }

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

MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass,
                                            CommandRecordingContext* commandContext) {
    ID3D11DeviceContext1* d3d11DeviceContext1 = commandContext->GetD3D11DeviceContext1();

    // Hold ID3D11RenderTargetView ComPtr to make attachments alive.
    ityp::array<ColorAttachmentIndex, ComPtr<ID3D11RenderTargetView>, kMaxColorAttachments>
        d3d11RenderTargetViews = {};
    ityp::array<ColorAttachmentIndex, ID3D11RenderTargetView*, kMaxColorAttachments>
        d3d11RenderTargetViewPtrs = {};
    ColorAttachmentIndex attachmentCount(uint8_t(0));
    for (ColorAttachmentIndex i :
         IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
        TextureView* colorTextureView = ToBackend(renderPass->colorAttachments[i].view.Get());
        DAWN_TRY_ASSIGN(d3d11RenderTargetViews[i], colorTextureView->CreateD3D11RenderTargetView());
        d3d11RenderTargetViewPtrs[i] = d3d11RenderTargetViews[i].Get();
        if (renderPass->colorAttachments[i].loadOp == wgpu::LoadOp::Clear) {
            std::array<float, 4> clearColor =
                ConvertToFloatColor(renderPass->colorAttachments[i].clearColor);
            d3d11DeviceContext1->ClearRenderTargetView(d3d11RenderTargetViews[i].Get(),
                                                       clearColor.data());
        }
        attachmentCount = i;
        attachmentCount++;
    }

    ComPtr<ID3D11DepthStencilView> d3d11DepthStencilView;
    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->CreateD3D11DepthStencilView(false, false));
        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;
        }

        d3d11DeviceContext1->ClearDepthStencilView(d3d11DepthStencilView.Get(), clearFlags,
                                                   attachmentInfo->clearDepth,
                                                   attachmentInfo->clearStencil);
    }

    d3d11DeviceContext1->OMSetRenderTargets(static_cast<uint8_t>(attachmentCount),
                                            d3d11RenderTargetViewPtrs.data(),
                                            d3d11DepthStencilView.Get());

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

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

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

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

                DAWN_TRY(bindGroupTracker.Apply());
                vertexBufferTracker.Apply(lastPipeline);
                DAWN_TRY(RecordFirstIndexOffset(lastPipeline, commandContext, draw->firstVertex,
                                                draw->firstInstance));
                commandContext->GetD3D11DeviceContext()->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);
                DAWN_TRY(RecordFirstIndexOffset(lastPipeline, commandContext, draw->baseVertex,
                                                draw->firstInstance));
                commandContext->GetD3D11DeviceContext()->DrawIndexedInstanced(
                    draw->indexCount, draw->instanceCount, draw->firstIndex, draw->baseVertex,
                    draw->firstInstance);

                break;
            }

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

                Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
                ASSERT(indirectBuffer != nullptr);

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

                if (lastPipeline->GetUsesVertexOrInstanceIndex()) {
                    // Copy StartVertexLocation and StartInstanceLocation into the uniform buffer
                    // for built-in variables.
                    uint64_t offset =
                        draw->indirectOffset +
                        offsetof(D3D11_DRAW_INSTANCED_INDIRECT_ARGS, StartVertexLocation);
                    DAWN_TRY(Buffer::Copy(commandContext, indirectBuffer, offset,
                                          sizeof(uint32_t) * 2, commandContext->GetUniformBuffer(),
                                          0));
                }

                commandContext->GetD3D11DeviceContext()->DrawInstancedIndirect(
                    indirectBuffer->GetD3D11NonConstantBuffer(), draw->indirectOffset);

                break;
            }

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

                Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
                ASSERT(indirectBuffer != nullptr);

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

                if (lastPipeline->GetUsesVertexOrInstanceIndex()) {
                    // Copy StartVertexLocation and StartInstanceLocation into the uniform buffer
                    // for built-in variables.
                    uint64_t offset =
                        draw->indirectOffset +
                        offsetof(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS, BaseVertexLocation);
                    DAWN_TRY(Buffer::Copy(commandContext, indirectBuffer, offset,
                                          sizeof(uint32_t) * 2, commandContext->GetUniformBuffer(),
                                          0));
                }

                commandContext->GetD3D11DeviceContext()->DrawIndexedInstancedIndirect(
                    indirectBuffer->GetD3D11NonConstantBuffer(), draw->indirectOffset);

                break;
            }

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

                lastPipeline = ToBackend(cmd->pipeline.Get());
                lastPipeline->ApplyNow(commandContext, blendColor, stencilReference);
                bindGroupTracker.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);

                commandContext->GetD3D11DeviceContext()->IASetIndexBuffer(
                    ToBackend(cmd->buffer)->GetD3D11NonConstantBuffer(), indexBufferFormat,
                    indexBufferBaseOffset);

                break;
            }

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

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

            default:
                UNREACHABLE();
                break;
        }

        return {};
    };

    Command type;
    while (mCommands.NextCommandId(&type)) {
        switch (type) {
            case Command::EndRenderPass: {
                mCommands.NextCommand<EndRenderPassCmd>();
                ID3D11DeviceContext* d3d11DeviceContext = commandContext->GetD3D11DeviceContext();
                d3d11DeviceContext->OMSetRenderTargets(0, nullptr, nullptr);

                if (renderPass->attachmentState->GetSampleCount() <= 1) {
                    return {};
                }

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

                    ASSERT(attachment.view->GetAspects() == Aspect::Color);
                    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,
                        resolveTexture->GetD3D11Format());
                }

                return {};
            }

            case Command::SetStencilReference: {
                SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
                stencilReference = cmd->reference;
                if (lastPipeline) {
                    lastPipeline->ApplyDepthStencilState(commandContext, 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->GetD3D11DeviceContext()->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->GetD3D11DeviceContext()->RSSetScissorRects(1, &scissorRect);
                break;
            }

            case Command::SetBlendConstant: {
                SetBlendConstantCmd* cmd = mCommands.NextCommand<SetBlendConstantCmd>();
                blendColor = ConvertToFloatColor(cmd->color);
                if (lastPipeline) {
                    lastPipeline->ApplyBlendState(commandContext, 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: {
                return DAWN_UNIMPLEMENTED_ERROR("BeginOcclusionQuery unimplemented.");
            }

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

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

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

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

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

        case Command::PopDebugGroup: {
            std::ignore = mCommands.NextCommand<PopDebugGroupCmd>();
            commandContext->GetD3DUserDefinedAnnotation()->EndEvent();
            break;
        }

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

MaybeError CommandBuffer::RecordFirstIndexOffset(RenderPipeline* renderPipeline,
                                                 CommandRecordingContext* commandContext,
                                                 uint32_t firstVertex,
                                                 uint32_t firstInstance) {
    if (!renderPipeline->GetUsesVertexOrInstanceIndex()) {
        // Vertex and instance index are not used in shader, so we don't need to update the uniform
        // buffer. The original value in the uniform buffer will not be used, so we don't need to
        // clear it.
        return {};
    }

    // TODO(dawn:1705): only update the uniform buffer when the value changes.
    uint32_t data[4] = {
        firstVertex,
        firstInstance,
    };
    DAWN_TRY(commandContext->GetUniformBuffer()->Write(commandContext, 0, data, sizeof(data)));

    return {};
}

MaybeError CommandBuffer::RecordNumWorkgroupsForDispatch(ComputePipeline* computePipeline,
                                                         CommandRecordingContext* commandContext,
                                                         DispatchCmd* dispatchCmd) {
    if (!computePipeline->UsesNumWorkgroups()) {
        // Workgroup size is not used in shader, so we don't need to update the uniform buffer. The
        // original value in the uniform buffer will not be used, so we don't need to clear it.
        return {};
    }

    uint32_t data[4] = {
        dispatchCmd->x,
        dispatchCmd->y,
        dispatchCmd->z,
    };
    DAWN_TRY(commandContext->GetUniformBuffer()->Write(commandContext, 0, data, sizeof(data)));

    return {};
}

}  // namespace dawn::native::d3d11
