// Copyright 2025 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.

#include "src/dawn/native/webgpu/CommandBufferWGPU.h"

#include <vector>

#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/native/CommandBuffer.h"
#include "src/dawn/native/RenderBundle.h"
#include "src/dawn/native/webgpu/BindGroupWGPU.h"
#include "src/dawn/native/webgpu/BufferWGPU.h"
#include "src/dawn/native/webgpu/CaptureContext.h"
#include "src/dawn/native/webgpu/CommandBufferHelpers.h"
#include "src/dawn/native/webgpu/ComputePipelineWGPU.h"
#include "src/dawn/native/webgpu/DeviceWGPU.h"
#include "src/dawn/native/webgpu/QuerySetWGPU.h"
#include "src/dawn/native/webgpu/RenderBundleWGPU.h"
#include "src/dawn/native/webgpu/RenderPipelineWGPU.h"
#include "src/dawn/native/webgpu/Serialization.h"
#include "src/dawn/native/webgpu/TextureWGPU.h"
#include "src/dawn/native/webgpu/ToWGPU.h"
#include "src/utils/assert.h"
#include "src/utils/compiler.h"

namespace dawn::native::webgpu {

// 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), RecordableObject(schema::ObjectType::CommandBuffer) {}

void CommandBuffer::SetLabelImpl() {
    ToBackend(GetDevice())->CaptureSetLabel(this, GetLabel());
}

namespace {

void PrepareResourcesForSyncScope(const SyncScopeResourceUsage& scope) {
    for (size_t i = 0; i < scope.textures.size(); i++) {
        Texture* texture = ToBackend(scope.textures[i]);

        texture->SynchronizeTextureBeforeUse();

        // Mark subresources as cleared that are not render attachments as initialized.
        // Render attachments will be marked as cleared in Encode BeginRenderPass.
        // The actual clearing relies on the inner device.
        scope.textureSyncInfos[i].Iterate(
            [&](const SubresourceRange& range, const TextureSyncInfo& syncInfo) -> void {
                if (syncInfo.usage & ~wgpu::TextureUsage::RenderAttachment) {
                    texture->SetIsSubresourceContentInitialized(true, range);
                }
            });
    }

    for (BufferBase* bufferBase : scope.buffers) {
        bufferBase->SetInitialized(true);
    }
}

void RecordComputePass(const DawnProcTable& wgpu,
                       WGPUCommandEncoder innerEncoder,
                       CommandIterator& commands,
                       BeginComputePassCmd* computePassCmd,
                       const ComputePassResourceUsage& resourceUsages) {
    WGPUComputePassDescriptor passDescriptor{
        .nextInChain = nullptr,
        .label = ToOutputStringView(computePassCmd->label),
        .timestampWrites = nullptr,
    };
    WGPUPassTimestampWrites timestampWrites;
    if (computePassCmd->timestampWrites.querySet) {
        timestampWrites = ToWGPU(computePassCmd->timestampWrites);
        passDescriptor.timestampWrites = &timestampWrites;
    }

    for (auto texture : resourceUsages.referencedTextures) {
        ToBackend(texture)->SynchronizeTextureBeforeUse();
    }

    WGPUComputePassEncoder passEncoder =
        wgpu.commandEncoderBeginComputePass(innerEncoder, &passDescriptor);

    size_t nextDispatchNumber = 0;
    Command type;
    while (commands.NextCommandId(&type)) {
        switch (type) {
            case Command::EndComputePass: {
                commands.NextCommand<EndComputePassCmd>();
                wgpu.computePassEncoderEnd(passEncoder);
                return;
            }

            case Command::Dispatch: {
                auto cmd = commands.NextCommand<DispatchCmd>();
                PrepareResourcesForSyncScope(resourceUsages.dispatchUsages[nextDispatchNumber]);
                ++nextDispatchNumber;
                wgpu.computePassEncoderDispatchWorkgroups(passEncoder, cmd->x, cmd->y, cmd->z);
                break;
            }

            case Command::DispatchIndirect: {
                auto cmd = commands.NextCommand<DispatchIndirectCmd>();
                PrepareResourcesForSyncScope(resourceUsages.dispatchUsages[nextDispatchNumber]);
                ++nextDispatchNumber;
                wgpu.computePassEncoderDispatchWorkgroupsIndirect(
                    passEncoder, ToBackend(cmd->indirectBuffer)->GetInnerHandle(),
                    cmd->indirectOffset);
                break;
            }

            case Command::SetComputePipeline: {
                auto cmd = commands.NextCommand<SetComputePipelineCmd>();
                wgpu.computePassEncoderSetPipeline(passEncoder,
                                                   ToBackend(cmd->pipeline)->GetInnerHandle());
                break;
            }

            case Command::SetBindGroup: {
                auto cmd = commands.NextCommand<SetBindGroupCmd>();
                ityp::span<BindingIndex, const uint32_t> dynamicOffsets;
                if (cmd->dynamicOffsetCount != BindingIndex{0u}) {
                    dynamicOffsets = commands.NextData<uint32_t>(cmd->dynamicOffsetCount);
                }

                wgpu.computePassEncoderSetBindGroup(passEncoder, static_cast<uint32_t>(cmd->index),
                                                    ToBackend(cmd->group)->GetInnerHandle(),
                                                    uint32_t{dynamicOffsets.size()},
                                                    dynamicOffsets.data());
                break;
            }
            case Command::InsertDebugMarker: {
                auto cmd = commands.NextCommand<InsertDebugMarkerCmd>();
                std::string_view label = NextNullTerminatedString(&commands, cmd->length);
                wgpu.computePassEncoderInsertDebugMarker(passEncoder, {label.data(), label.size()});
                break;
            }

            case Command::PopDebugGroup: {
                commands.NextCommand<PopDebugGroupCmd>();
                wgpu.computePassEncoderPopDebugGroup(passEncoder);
                break;
            }

            case Command::PushDebugGroup: {
                auto cmd = commands.NextCommand<PushDebugGroupCmd>();
                std::string_view label = NextNullTerminatedString(&commands, cmd->length);
                wgpu.computePassEncoderPushDebugGroup(passEncoder, {label.data(), label.size()});
                break;
            }

            case Command::WriteTimestamp: {
                auto cmd = commands.NextCommand<WriteTimestampCmd>();
                wgpu.computePassEncoderWriteTimestamp(passEncoder,
                                                      ToBackend(cmd->querySet)->GetInnerHandle(),
                                                      uint32_t{cmd->queryIndex});
                break;
            }

            case Command::SetImmediates: {
                auto cmd = commands.NextCommand<SetImmediatesCmd>();
                DAWN_ASSERT(cmd->size > 0);
                Span<const uint8_t> data = commands.NextData<uint8_t>(cmd->size);
                wgpu.computePassEncoderSetImmediates(passEncoder, cmd->offset, data.data(),
                                                     data.size());
                break;
            }

            default: {
                DAWN_UNREACHABLE();
                break;
            }
        }
    }

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

void RecordRenderPass(const Device* device,
                      WGPUCommandEncoder innerEncoder,
                      CommandIterator& commands,
                      BeginRenderPassCmd* renderPassCmd) {
    const DawnProcTable& wgpu = device->wgpu.get();

    PerColorAttachment<WGPURenderPassColorAttachment> colorAttachments = {};

    size_t colorAttachmentCount = 0;
    for (auto i : renderPassCmd->attachmentState->GetColorAttachmentsMask()) {
        auto& colorAttachment = renderPassCmd->colorAttachments[i];
        colorAttachments[i] = ToWGPU(colorAttachment);
        colorAttachmentCount = static_cast<size_t>(i) + 1;
    }

    WGPURenderPassDescriptor passDescriptor{
        .nextInChain = nullptr,
        .label = ToOutputStringView(renderPassCmd->label),
        .colorAttachmentCount = colorAttachmentCount,
        .colorAttachments = colorAttachments.data(),
        .depthStencilAttachment = nullptr,
        .occlusionQuerySet = renderPassCmd->occlusionQuerySet
                                 ? ToBackend(renderPassCmd->occlusionQuerySet)->GetInnerHandle()
                                 : nullptr,
        .timestampWrites = nullptr,
    };
    WGPURenderPassDepthStencilAttachment depthStencilAttachment;
    if (renderPassCmd->attachmentState->HasDepthStencilAttachment()) {
        depthStencilAttachment = ToWGPU(renderPassCmd->depthStencilAttachment);
        passDescriptor.depthStencilAttachment = &depthStencilAttachment;
    }
    WGPUPassTimestampWrites timestampWrites;
    if (renderPassCmd->timestampWrites.querySet) {
        timestampWrites = ToWGPU(renderPassCmd->timestampWrites);
        passDescriptor.timestampWrites = &timestampWrites;
    }
    WGPURenderPassDescriptorResolveRect resolveRect;
    if (renderPassCmd->resolveRect.HasValue()) {
        resolveRect = WGPU_RENDER_PASS_DESCRIPTOR_RESOLVE_RECT_INIT;
        resolveRect.colorOffsetX = renderPassCmd->resolveRect.colorOffsetX;
        resolveRect.colorOffsetY = renderPassCmd->resolveRect.colorOffsetY;
        resolveRect.resolveOffsetX = renderPassCmd->resolveRect.resolveOffsetX;
        resolveRect.resolveOffsetY = renderPassCmd->resolveRect.resolveOffsetY;
        resolveRect.width = renderPassCmd->resolveRect.updateWidth;
        resolveRect.height = renderPassCmd->resolveRect.updateHeight;
        passDescriptor.nextInChain = &(resolveRect.chain);
    }
    WGPURenderPassEncoder passEncoder =
        wgpu.commandEncoderBeginRenderPass(innerEncoder, &passDescriptor);

    Command type;
    while (commands.NextCommandId(&type)) {
        switch (type) {
            case Command::EndRenderPass: {
                commands.NextCommand<EndRenderPassCmd>();
                wgpu.renderPassEncoderEnd(passEncoder);
                return;
            }

            case Command::SetBlendConstant: {
                auto cmd = commands.NextCommand<SetBlendConstantCmd>();
                WGPUColor color = ToWGPU(cmd->color);
                wgpu.renderPassEncoderSetBlendConstant(passEncoder, &color);
                break;
            }

            case Command::SetStencilReference: {
                auto cmd = commands.NextCommand<SetStencilReferenceCmd>();
                wgpu.renderPassEncoderSetStencilReference(passEncoder, cmd->reference);
                break;
            }

            case Command::SetViewport: {
                auto cmd = commands.NextCommand<SetViewportCmd>();
                wgpu.renderPassEncoderSetViewport(passEncoder, cmd->x, cmd->y, cmd->width,
                                                  cmd->height, cmd->minDepth, cmd->maxDepth);
                break;
            }

            case Command::SetScissorRect: {
                auto cmd = commands.NextCommand<SetScissorRectCmd>();
                wgpu.renderPassEncoderSetScissorRect(passEncoder, cmd->x, cmd->y, cmd->width,
                                                     cmd->height);
                break;
            }

            case Command::ExecuteBundles: {
                auto* cmd = commands.NextCommand<ExecuteBundlesCmd>();
                auto bundles = commands.NextData<Ref<RenderBundleBase>>(cmd->count);
                std::vector<WGPURenderBundle> wgpuBundles;
                wgpuBundles.reserve(bundles.size());

                for (const auto& bundle : bundles) {
                    wgpuBundles.push_back(ToBackend(bundle.Get())->GetInnerHandle());
                }
                wgpu.renderPassEncoderExecuteBundles(passEncoder, wgpuBundles.size(),
                                                     wgpuBundles.data());
                break;
            }

            case Command::BeginOcclusionQuery: {
                auto cmd = commands.NextCommand<BeginOcclusionQueryCmd>();
                wgpu.renderPassEncoderBeginOcclusionQuery(passEncoder, uint32_t{cmd->queryIndex});
                break;
            }

            case Command::EndOcclusionQuery: {
                commands.NextCommand<EndOcclusionQueryCmd>();
                wgpu.renderPassEncoderEndOcclusionQuery(passEncoder);
                break;
            }

            case Command::WriteTimestamp: {
                auto cmd = commands.NextCommand<WriteTimestampCmd>();
                wgpu.renderPassEncoderWriteTimestamp(passEncoder,
                                                     ToBackend(cmd->querySet)->GetInnerHandle(),
                                                     uint32_t{cmd->queryIndex});
                break;
            }

            // The followings are commands shared with RenderBundleEncoder, but it's a bit hard to
            // share code with EncodeRenderBundleCommand since we are using webgpu C header.
            case Command::Draw: {
                auto cmd = commands.NextCommand<DrawCmd>();
                wgpu.renderPassEncoderDraw(passEncoder, cmd->vertexCount, cmd->instanceCount,
                                           cmd->firstVertex, cmd->firstInstance);
                break;
            }

            case Command::DrawIndexed: {
                auto cmd = commands.NextCommand<DrawIndexedCmd>();
                wgpu.renderPassEncoderDrawIndexed(passEncoder, cmd->indexCount, cmd->instanceCount,
                                                  cmd->firstIndex, cmd->baseVertex,
                                                  cmd->firstInstance);
                break;
            }

            case Command::DrawIndirect: {
                auto cmd = commands.NextCommand<DrawIndirectCmd>();
                wgpu.renderPassEncoderDrawIndirect(passEncoder,
                                                   ToBackend(cmd->indirectBuffer)->GetInnerHandle(),
                                                   cmd->indirectOffset);
                break;
            }

            case Command::DrawIndexedIndirect: {
                auto cmd = commands.NextCommand<DrawIndexedIndirectCmd>();
                wgpu.renderPassEncoderDrawIndexedIndirect(
                    passEncoder, ToBackend(cmd->indirectBuffer)->GetInnerHandle(),
                    cmd->indirectOffset);
                break;
            }

            case Command::MultiDrawIndirect: {
                DAWN_UNREACHABLE();
                break;
            }

            case Command::MultiDrawIndexedIndirect: {
                DAWN_UNREACHABLE();
                break;
            }

            case Command::InsertDebugMarker: {
                auto cmd = commands.NextCommand<InsertDebugMarkerCmd>();
                std::string_view label = NextNullTerminatedString(&commands, cmd->length);
                wgpu.renderPassEncoderInsertDebugMarker(passEncoder, {label.data(), label.size()});
                break;
            }

            case Command::PopDebugGroup: {
                commands.NextCommand<PopDebugGroupCmd>();
                wgpu.renderPassEncoderPopDebugGroup(passEncoder);
                break;
            }

            case Command::PushDebugGroup: {
                auto cmd = commands.NextCommand<PushDebugGroupCmd>();
                std::string_view label = NextNullTerminatedString(&commands, cmd->length);
                wgpu.renderPassEncoderPushDebugGroup(passEncoder, {label.data(), label.size()});
                break;
            }

            case Command::SetBindGroup: {
                auto cmd = commands.NextCommand<SetBindGroupCmd>();
                ityp::span<BindingIndex, const uint32_t> dynamicOffsets;
                if (cmd->dynamicOffsetCount != BindingIndex{0u}) {
                    dynamicOffsets = commands.NextData<uint32_t>(cmd->dynamicOffsetCount);
                }
                wgpu.renderPassEncoderSetBindGroup(passEncoder, static_cast<uint32_t>(cmd->index),
                                                   ToBackend(cmd->group)->GetInnerHandle(),
                                                   uint32_t{dynamicOffsets.size()},
                                                   dynamicOffsets.data());
                break;
            }

            case Command::SetIndexBuffer: {
                auto cmd = commands.NextCommand<SetIndexBufferCmd>();
                wgpu.renderPassEncoderSetIndexBuffer(passEncoder,
                                                     ToBackend(cmd->buffer)->GetInnerHandle(),
                                                     ToWGPU(cmd->format), cmd->offset, cmd->size);
                break;
            }

            case Command::SetRenderPipeline: {
                auto cmd = commands.NextCommand<SetRenderPipelineCmd>();
                wgpu.renderPassEncoderSetPipeline(passEncoder,
                                                  ToBackend(cmd->pipeline)->GetInnerHandle());
                break;
            }

            case Command::SetVertexBuffer: {
                auto cmd = commands.NextCommand<SetVertexBufferCmd>();
                wgpu.renderPassEncoderSetVertexBuffer(passEncoder, static_cast<uint8_t>(cmd->slot),
                                                      ToBackend(cmd->buffer)->GetInnerHandle(),
                                                      cmd->offset, cmd->size);
                break;
            }

            case Command::SetImmediates: {
                auto cmd = commands.NextCommand<SetImmediatesCmd>();
                DAWN_ASSERT(cmd->size > 0);
                Span<const uint8_t> data = commands.NextData<uint8_t>(cmd->size);
                wgpu.renderPassEncoderSetImmediates(passEncoder, cmd->offset, data.data(),
                                                    data.size());
                break;
            }

            default: {
                DAWN_UNREACHABLE();
                break;
            }
        }
    }

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

MaybeError GatherReferencedResourcesFromComputePass(CaptureContext& captureContext,
                                                    CommandIterator& commands,
                                                    CommandBufferResourceUsages& usedResources) {
    Command type;
    while (commands.NextCommandId(&type)) {
        switch (type) {
            case Command::EndComputePass: {
                commands.NextCommand<EndComputePassCmd>();
                return {};
            }
            case Command::SetComputePipeline: {
                auto cmd = commands.NextCommand<SetComputePipelineCmd>();
                usedResources.computePipelines.push_back(cmd->pipeline.Get());
                break;
            }
            case Command::SetBindGroup: {
                auto cmd = commands.NextCommand<SetBindGroupCmd>();
                if (cmd->dynamicOffsetCount > BindingIndex{0u}) {
                    commands.NextData<uint32_t>(cmd->dynamicOffsetCount);
                }
                usedResources.bindGroups.push_back(cmd->group.Get());
                break;
            }
            case Command::Dispatch:
            case Command::DispatchIndirect:
            case Command::WriteTimestamp:
            case Command::SetImmediates:
            case Command::PushDebugGroup:
            case Command::InsertDebugMarker:
            case Command::PopDebugGroup:
                SkipCommand(&commands, type);
                break;
            default: {
                return DAWN_UNIMPLEMENTED_ERROR("Unimplemented command");
            }
        }
    }

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

MaybeError GatherReferencedResourcesFromRenderPass(CaptureContext& captureContext,
                                                   CommandIterator& commands,
                                                   CommandBufferResourceUsages& usedResources) {
    Command type;
    while (commands.NextCommandId(&type)) {
        switch (type) {
            case Command::EndRenderPass: {
                commands.NextCommand<EndRenderPassCmd>();
                return {};
            }
            case Command::ExecuteBundles: {
                auto cmd = commands.NextCommand<ExecuteBundlesCmd>();
                auto bundles = commands.NextData<Ref<RenderBundleBase>>(cmd->count);
                for (const auto& bundle : bundles) {
                    usedResources.renderBundles.push_back(bundle.Get());
                }
                break;
            }
            default:
                DAWN_TRY(GatherReferencedResourcesFromRenderCommand(captureContext, commands,
                                                                    usedResources, type));
                break;
        }
    }

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

void CaptureTimestampWriteCommand(CaptureContext& captureContext, CommandIterator& commands) {
    const auto& cmd = *commands.NextCommand<WriteTimestampCmd>();
    schema::CommandBufferCommandWriteTimestampCmd data{{
        .data = {{
            .querySetId = captureContext.GetId(cmd.querySet),
            .queryIndex = uint32_t{cmd.queryIndex},
        }},
    }};
    Serialize(captureContext, data);
}

MaybeError CaptureComputePass(CaptureContext& captureContext, CommandIterator& commands) {
    Command type;
    while (commands.NextCommandId(&type)) {
        switch (type) {
            case Command::EndComputePass: {
                commands.NextCommand<EndComputePassCmd>();
                Serialize(captureContext, schema::CommandBufferCommand::End);
                return {};
            }
            case Command::SetComputePipeline: {
                const auto& cmd = *commands.NextCommand<SetComputePipelineCmd>();
                schema::CommandBufferCommandSetComputePipelineCmd data{{
                    .data = {{
                        .pipelineId = captureContext.GetId(cmd.pipeline.Get()),
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::Dispatch: {
                const auto& cmd = *commands.NextCommand<DispatchCmd>();
                schema::CommandBufferCommandDispatchCmd data{{
                    .data = {{
                        .x = cmd.x,
                        .y = cmd.y,
                        .z = cmd.z,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::DispatchIndirect: {
                const auto& cmd = *commands.NextCommand<DispatchIndirectCmd>();
                schema::CommandBufferCommandDispatchIndirectCmd data{{
                    .data = {{
                        .bufferId = captureContext.GetId(cmd.indirectBuffer),
                        .offset = cmd.indirectOffset,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::WriteTimestamp:
                CaptureTimestampWriteCommand(captureContext, commands);
                break;
            case Command::SetBindGroup:
            case Command::SetImmediates:
                CaptureSharedCommand(captureContext, commands, type);
                break;
            case Command::PushDebugGroup:
            case Command::PopDebugGroup:
            case Command::InsertDebugMarker:
                CaptureDebugCommand(captureContext, commands, type);
                break;
            default:
                return DAWN_UNIMPLEMENTED_ERROR("Unimplemented command");
        }
    }
    return {};
}

MaybeError CaptureRenderPass(CaptureContext& captureContext, CommandIterator& commands) {
    Command type;
    while (commands.NextCommandId(&type)) {
        switch (type) {
            case Command::EndRenderPass: {
                commands.NextCommand<EndRenderPassCmd>();
                Serialize(captureContext, schema::CommandBufferCommand::End);
                return {};
            }
            case Command::ExecuteBundles: {
                const auto& cmd = *commands.NextCommand<ExecuteBundlesCmd>();
                auto bundles = commands.NextData<Ref<RenderBundleBase>>(cmd.count);
                std::vector<schema::ObjectId> bundleIds;
                for (const auto& bundle : bundles) {
                    bundleIds.push_back(captureContext.GetId(bundle.Get()));
                }
                schema::CommandBufferCommandExecuteBundlesCmd data{{
                    .data = {{
                        .bundleIds = bundleIds,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::BeginOcclusionQuery: {
                const auto& cmd = *commands.NextCommand<BeginOcclusionQueryCmd>();
                schema::CommandBufferCommandBeginOcclusionQueryCmd data{{
                    .data = {{
                        .queryIndex = uint32_t{cmd.queryIndex},
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::EndOcclusionQuery: {
                commands.NextCommand<EndOcclusionQueryCmd>();
                Serialize(captureContext, schema::CommandBufferCommand::EndOcclusionQuery);
                break;
            }
            case Command::SetBlendConstant: {
                const auto& cmd = *commands.NextCommand<SetBlendConstantCmd>();
                schema::CommandBufferCommandSetBlendConstantCmd data{{
                    .data = {{
                        .color = ToSchema(cmd.color),
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::SetScissorRect: {
                const auto& cmd = *commands.NextCommand<SetScissorRectCmd>();
                schema::CommandBufferCommandSetScissorRectCmd data{{
                    .data = {{
                        .x = cmd.x,
                        .y = cmd.y,
                        .width = cmd.width,
                        .height = cmd.height,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::SetStencilReference: {
                const auto& cmd = *commands.NextCommand<SetStencilReferenceCmd>();
                schema::CommandBufferCommandSetStencilReferenceCmd data{{
                    .data = {{
                        .reference = cmd.reference,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::SetViewport: {
                const auto& cmd = *commands.NextCommand<SetViewportCmd>();
                schema::CommandBufferCommandSetViewportCmd data{{
                    .data = {{
                        .x = cmd.x,
                        .y = cmd.y,
                        .width = cmd.width,
                        .height = cmd.height,
                        .minDepth = cmd.minDepth,
                        .maxDepth = cmd.maxDepth,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::WriteTimestamp:
                CaptureTimestampWriteCommand(captureContext, commands);
                break;
            default:
                DAWN_TRY(CaptureRenderCommand(captureContext, commands, type));
                break;
        }
    }
    return {};
}

MaybeError AddReferencedPassResourceUsages(CaptureContext& captureContext,
                                           const SyncScopeResourceUsage& usages) {
    for (auto buffer : usages.buffers) {
        DAWN_TRY(captureContext.AddResource(ToBackend(buffer)));
    }
    for (auto texture : usages.textures) {
        DAWN_TRY(captureContext.AddResource(ToBackend(texture)));
    }
    return {};
}

}  // anonymous namespace

MaybeError CommandBuffer::AddReferenced(CaptureContext& captureContext) {
    const auto& resourceUsages = GetResourceUsages();
    for (auto buffer : resourceUsages.topLevelBuffers) {
        DAWN_TRY(captureContext.AddResource(ToBackend(buffer)));
    }
    for (auto texture : resourceUsages.topLevelTextures) {
        DAWN_TRY(captureContext.AddResource(ToBackend(texture)));
    }
    for (auto querySet : resourceUsages.usedQuerySets) {
        DAWN_TRY(captureContext.AddResource(ToBackend(querySet)));
    }
    for (const auto& usages : resourceUsages.renderPasses) {
        DAWN_TRY(AddReferencedPassResourceUsages(captureContext, usages));
    }
    for (const auto& pass : resourceUsages.computePasses) {
        for (const auto& usages : pass.dispatchUsages) {
            DAWN_TRY(AddReferencedPassResourceUsages(captureContext, usages));
        }
    }

    CommandBufferResourceUsages usedResources;

    CommandIterator& commands = mCommands;
    Command type;
    while (commands.NextCommandId(&type)) {
        switch (type) {
            case Command::BeginComputePass: {
                const auto& cmd = *commands.NextCommand<BeginComputePassCmd>();
                if (cmd.timestampWrites.querySet != nullptr) {
                    DAWN_TRY(
                        captureContext.AddResource(ToBackend(cmd.timestampWrites.querySet.Get())));
                }
                DAWN_TRY(GatherReferencedResourcesFromComputePass(captureContext, commands,
                                                                  usedResources));
                break;
            }
            case Command::BeginRenderPass: {
                const auto& cmd = *commands.NextCommand<BeginRenderPassCmd>();
                for (const auto& attachment : cmd.colorAttachments) {
                    if (attachment.view != nullptr) {
                        DAWN_TRY(captureContext.AddResource(ToBackend(attachment.view.Get())));
                    }
                    if (attachment.resolveTarget != nullptr) {
                        DAWN_TRY(
                            captureContext.AddResource(ToBackend(attachment.resolveTarget.Get())));
                    }
                }
                if (cmd.depthStencilAttachment.view != nullptr) {
                    DAWN_TRY(captureContext.AddResource(
                        ToBackend(cmd.depthStencilAttachment.view.Get())));
                }
                if (cmd.timestampWrites.querySet != nullptr) {
                    DAWN_TRY(
                        captureContext.AddResource(ToBackend(cmd.timestampWrites.querySet.Get())));
                }
                if (cmd.occlusionQuerySet != nullptr) {
                    DAWN_TRY(captureContext.AddResource(ToBackend(cmd.occlusionQuerySet.Get())));
                }
                DAWN_TRY(GatherReferencedResourcesFromRenderPass(captureContext, commands,
                                                                 usedResources));
                break;
            }
            case Command::WriteBuffer:
            case Command::ClearBuffer:
            case Command::CopyBufferToBuffer:
            case Command::CopyBufferToTexture:
            case Command::CopyTextureToBuffer:
            case Command::CopyTextureToTexture:
            case Command::ResolveQuerySet:
            case Command::WriteTimestamp:
            case Command::PushDebugGroup:
            case Command::InsertDebugMarker:
            case Command::PopDebugGroup:
                SkipCommand(&commands, type);
                break;
            default: {
                return DAWN_UNIMPLEMENTED_ERROR("Unimplemented command");
            }
        }
    }

    DAWN_TRY(AddUsedResources(captureContext, usedResources));

    return {};
}

schema::ColorAttachment ToSchema(CaptureContext& captureContext,
                                 const RenderPassColorAttachmentInfo& info) {
    return {{
        .viewId = captureContext.GetId(info.view),
        .depthSlice = info.view->GetDimension() == wgpu::TextureViewDimension::e3D
                          ? info.depthSlice
                          : wgpu::kDepthSliceUndefined,
        .resolveTargetId = captureContext.GetId(info.resolveTarget),
        .loadOp = info.loadOp,
        .storeOp = info.storeOp,
        .clearValue = ToSchema(info.clearColor),
    }};
}

schema::RenderPassDepthStencilAttachment ToSchema(
    CaptureContext& captureContext,
    const RenderPassDepthStencilAttachmentInfo& info) {
    // The front end does not save the user's actual loadOp/storeOp settings so we derive what they
    // were.
    // TODO(460491958): Save the actual user's loadOp/storeOp settings and adjust the backends.
    wgpu::LoadOp depthLoadOp = info.depthLoadOp;
    wgpu::StoreOp depthStoreOp = info.depthStoreOp;
    wgpu::LoadOp stencilLoadOp = info.stencilLoadOp;
    wgpu::StoreOp stencilStoreOp = info.stencilStoreOp;

    bool haveAttachment = info.view != nullptr;
    bool haveDepth = haveAttachment && info.view->GetFormat().HasDepth();
    bool haveStencil = haveAttachment && info.view->GetFormat().HasStencil();

    if (!haveAttachment || !haveDepth || info.depthReadOnly) {
        depthLoadOp = wgpu::LoadOp::Undefined;
        depthStoreOp = wgpu::StoreOp::Undefined;
    }

    if (!haveAttachment || !haveStencil || info.stencilReadOnly) {
        stencilLoadOp = wgpu::LoadOp::Undefined;
        stencilStoreOp = wgpu::StoreOp::Undefined;
    }

    return {{
        .viewId = captureContext.GetId(info.view),
        .depthLoadOp = depthLoadOp,
        .depthStoreOp = depthStoreOp,
        .depthClearValue = info.clearDepth,
        .depthReadOnly = info.depthReadOnly,
        .stencilLoadOp = stencilLoadOp,
        .stencilStoreOp = stencilStoreOp,
        .stencilClearValue = info.clearStencil,
        .stencilReadOnly = info.stencilReadOnly,
    }};
}

MaybeError CommandBuffer::CaptureCreationParameters(CaptureContext& captureContext) {
    CommandIterator& commands = mCommands;
    Command type;
    while (commands.NextCommandId(&type)) {
        switch (type) {
            case Command::CopyBufferToBuffer: {
                const auto& cmd = *commands.NextCommand<CopyBufferToBufferCmd>();
                schema::CommandBufferCommandCopyBufferToBufferCmd data{{
                    .data = {{
                        .srcBufferId = captureContext.GetId(cmd.source.Get()),
                        .srcOffset = cmd.sourceOffset,
                        .dstBufferId = captureContext.GetId(cmd.destination.Get()),
                        .dstOffset = cmd.destinationOffset,
                        .size = cmd.size,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::CopyBufferToTexture: {
                const auto& cmd = *commands.NextCommand<CopyBufferToTextureCmd>();
                const TypedTexelBlockInfo& blockInfo = GetBlockInfo(cmd.destination);
                schema::CommandBufferCommandCopyBufferToTextureCmd data{{
                    .data = {{
                        .source = ToSchema(captureContext, cmd.source, blockInfo),
                        .destination = ToSchema(captureContext, cmd.destination),
                        .copySize = ToSchema(cmd.copySize),
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::CopyTextureToBuffer: {
                const auto& cmd = *commands.NextCommand<CopyTextureToBufferCmd>();
                const TypedTexelBlockInfo& blockInfo = GetBlockInfo(cmd.source);
                schema::CommandBufferCommandCopyTextureToBufferCmd data{{
                    .data = {{
                        .source = ToSchema(captureContext, cmd.source),
                        .destination = ToSchema(captureContext, cmd.destination, blockInfo),
                        .copySize = ToSchema(cmd.copySize),
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::CopyTextureToTexture: {
                const auto& cmd = *commands.NextCommand<CopyTextureToTextureCmd>();
                schema::CommandBufferCommandCopyTextureToTextureCmd data{{
                    .data = {{
                        .source = ToSchema(captureContext, cmd.source),
                        .destination = ToSchema(captureContext, cmd.destination),
                        .copySize = ToSchema(cmd.copySize),
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::ClearBuffer: {
                const auto& cmd = *commands.NextCommand<ClearBufferCmd>();
                schema::CommandBufferCommandClearBufferCmd data{{
                    .data = {{
                        .bufferId = captureContext.GetId(cmd.buffer.Get()),
                        .offset = cmd.offset,
                        .size = cmd.size,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::WriteBuffer: {
                const auto& cmd = *commands.NextCommand<WriteBufferCmd>();
                Span<const uint8_t> values = commands.NextData<uint8_t>(cmd.size);
                schema::CommandBufferCommandWriteBufferCmd data{{
                    .data = {{
                        .bufferId = captureContext.GetId(cmd.buffer.Get()),
                        .bufferOffset = cmd.offset,
                        .data = std::vector(values.begin(), values.end()),
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::BeginComputePass: {
                const auto& cmd = *commands.NextCommand<BeginComputePassCmd>();
                schema::CommandBufferCommandBeginComputePassCmd data{{
                    .data = {{
                        .label = cmd.label,
                        .timestampWrites = ToSchema(captureContext, cmd.timestampWrites),
                    }},
                }};
                Serialize(captureContext, data);
                // Capture commands inside the compute pass
                DAWN_TRY(CaptureComputePass(captureContext, commands));
                break;
            }
            case Command::BeginRenderPass: {
                const auto& cmd = *commands.NextCommand<BeginRenderPassCmd>();

                // The front end does not store the number of attachments but the API requires that
                // we provide them for sparse attachments so we initialize colorAttachments with
                // enough slots to cover all used slots and fill them with a state that will be set
                // to unused on replay.
                ColorAttachmentMask attachmentMask = cmd.attachmentState->GetColorAttachmentsMask();
                ColorAttachmentIndex attachmentCount = GetHighestBitIndexPlusOne(attachmentMask);

                std::vector<schema::ColorAttachment> colorAttachments(size_t{attachmentCount},
                                                                      schema::ColorAttachment{});
                for (ColorAttachmentIndex slot : attachmentMask) {
                    colorAttachments[size_t{slot}] =
                        ToSchema(captureContext, cmd.colorAttachments[slot]);
                }

                schema::ResolveRect resolveRect = {};
                if (cmd.resolveRect.HasValue()) {
                    resolveRect.colorOffsetX = cmd.resolveRect.colorOffsetX;
                    resolveRect.colorOffsetY = cmd.resolveRect.colorOffsetY;
                    resolveRect.resolveOffsetX = cmd.resolveRect.resolveOffsetX;
                    resolveRect.resolveOffsetY = cmd.resolveRect.resolveOffsetY;
                    resolveRect.width = cmd.resolveRect.updateWidth;
                    resolveRect.height = cmd.resolveRect.updateHeight;
                }

                schema::CommandBufferCommandBeginRenderPassCmd data{{
                    .data = {{
                        .label = cmd.label,
                        .colorAttachments = colorAttachments,
                        .depthStencilAttachment =
                            ToSchema(captureContext, cmd.depthStencilAttachment),
                        .occlusionQuerySetId = captureContext.GetId(cmd.occlusionQuerySet.Get()),
                        .timestampWrites = ToSchema(captureContext, cmd.timestampWrites),
                        .resolveRect = resolveRect,
                    }},
                }};
                Serialize(captureContext, data);
                // Capture commands inside the compute pass
                DAWN_TRY(CaptureRenderPass(captureContext, commands));
                break;
            }
            case Command::ResolveQuerySet: {
                const auto& cmd = *commands.NextCommand<ResolveQuerySetCmd>();
                schema::CommandBufferCommandResolveQuerySetCmd data{{
                    .data = {{
                        .querySetId = captureContext.GetId(cmd.querySet.Get()),
                        .firstQuery = uint32_t{cmd.firstQuery},
                        .queryCount = uint32_t{cmd.queryCount},
                        .destinationId = captureContext.GetId(cmd.destination.Get()),
                        .destinationOffset = cmd.destinationOffset,
                    }},
                }};
                Serialize(captureContext, data);
                break;
            }
            case Command::WriteTimestamp:
                CaptureTimestampWriteCommand(captureContext, commands);
                break;
            case Command::PushDebugGroup:
            case Command::PopDebugGroup:
            case Command::InsertDebugMarker:
                CaptureDebugCommand(captureContext, commands, type);
                break;
            default:
                return DAWN_UNIMPLEMENTED_ERROR("Unimplemented command");
        }
    }
    Serialize(captureContext, schema::CommandBufferCommand::End);
    return {};
}

ResultOrError<WGPUCommandBuffer> CommandBuffer::RecordCommands() {
    auto& wgpu = ToBackend(GetDevice())->wgpu.get();

    // TODO(crbug.com/413053623): Use stored command encoder descriptor
    WGPUCommandEncoder innerEncoder =
        wgpu.deviceCreateCommandEncoder(ToBackend(GetDevice())->GetInnerHandle(), nullptr);

    PassIndex nextComputePassNumber{0u};
    PassIndex nextRenderPassNumber{0u};

    Command type;
    while (mCommands.NextCommandId(&type)) {
        switch (type) {
            case Command::BeginComputePass: {
                BeginComputePassCmd* cmd = mCommands.NextCommand<BeginComputePassCmd>();
                RecordComputePass(wgpu, innerEncoder, mCommands, cmd,
                                  GetResourceUsages().computePasses[nextComputePassNumber]);
                ++nextComputePassNumber;
                break;
            }
            case Command::BeginRenderPass: {
                auto cmd = mCommands.NextCommand<BeginRenderPassCmd>();

                // Call PrepareResourcesForSyncScope instead of manually set every texture with
                // SetInitialized(true) to properly manage initialization state especially for
                // imported shared texture.
                PrepareResourcesForSyncScope(
                    GetResourceUsages().renderPasses[nextRenderPassNumber]);

                DAWN_TRY(LazyClearRenderPassAttachments(
                    GetDevice(), cmd,
                    [](TextureBase* texture, const SubresourceRange& range) -> MaybeError {
                        // The WGPU backend doesn't clear directly, it relies on the the inner
                        // device so we just mark the subresource as initialized.
                        ToBackend(texture)->SetIsSubresourceContentInitialized(true, range);
                        return {};
                    }));
                RecordRenderPass(ToBackend(GetDevice()), innerEncoder, mCommands, cmd);

                ++nextRenderPassNumber;
                break;
            }
            case Command::CopyBufferToBuffer: {
                auto copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
                wgpu.commandEncoderCopyBufferToBuffer(
                    innerEncoder, ToBackend(copy->source)->GetInnerHandle(), copy->sourceOffset,
                    ToBackend(copy->destination)->GetInnerHandle(), copy->destinationOffset,
                    copy->size);
                break;
            }
            case Command::CopyBufferToTexture: {
                auto cmd = mCommands.NextCommand<CopyBufferToTextureCmd>();
                const TypedTexelBlockInfo& blockInfo = GetBlockInfo(cmd->destination);
                WGPUTexelCopyBufferInfo source = ToWGPU(cmd->source, blockInfo);
                WGPUTexelCopyTextureInfo destination = ToWGPU(cmd->destination);
                WGPUExtent3D size = ToWGPU(cmd->copySize);
                ToBackend(cmd->destination.texture.Get())->SynchronizeTextureBeforeUse();
                wgpu.commandEncoderCopyBufferToTexture(innerEncoder, &source, &destination, &size);
                cmd->destination.texture.Get()->SetIsSubresourceContentInitialized(
                    true, GetSubresourcesAffectedByCopy(cmd->destination, cmd->copySize));
                break;
            }
            case Command::CopyTextureToBuffer: {
                auto cmd = mCommands.NextCommand<CopyTextureToBufferCmd>();
                const TypedTexelBlockInfo& blockInfo = GetBlockInfo(cmd->source);
                WGPUTexelCopyTextureInfo source = ToWGPU(cmd->source);
                WGPUTexelCopyBufferInfo destination = ToWGPU(cmd->destination, blockInfo);
                WGPUExtent3D size = ToWGPU(cmd->copySize);
                ToBackend(cmd->source.texture.Get())->SynchronizeTextureBeforeUse();
                wgpu.commandEncoderCopyTextureToBuffer(innerEncoder, &source, &destination, &size);
                break;
            }
            case Command::CopyTextureToTexture: {
                auto cmd = mCommands.NextCommand<CopyTextureToTextureCmd>();
                WGPUTexelCopyTextureInfo source = ToWGPU(cmd->source);
                WGPUTexelCopyTextureInfo destination = ToWGPU(cmd->destination);
                WGPUExtent3D size = ToWGPU(cmd->copySize);
                ToBackend(cmd->source.texture.Get())->SynchronizeTextureBeforeUse();
                ToBackend(cmd->destination.texture.Get())->SynchronizeTextureBeforeUse();
                wgpu.commandEncoderCopyTextureToTexture(innerEncoder, &source, &destination, &size);
                cmd->destination.texture.Get()->SetIsSubresourceContentInitialized(
                    true, GetSubresourcesAffectedByCopy(cmd->destination, cmd->copySize));
                break;
            }
            case Command::ClearBuffer: {
                auto cmd = mCommands.NextCommand<ClearBufferCmd>();
                wgpu.commandEncoderClearBuffer(
                    innerEncoder, ToBackend(cmd->buffer)->GetInnerHandle(), cmd->offset, cmd->size);
                break;
            }
            case Command::ResolveQuerySet: {
                auto cmd = mCommands.NextCommand<ResolveQuerySetCmd>();
                wgpu.commandEncoderResolveQuerySet(
                    innerEncoder, ToBackend(cmd->querySet)->GetInnerHandle(),
                    uint32_t{cmd->firstQuery}, uint32_t{cmd->queryCount},
                    ToBackend(cmd->destination)->GetInnerHandle(), cmd->destinationOffset);
                break;
            }
            case Command::WriteTimestamp: {
                auto cmd = mCommands.NextCommand<WriteTimestampCmd>();
                wgpu.commandEncoderWriteTimestamp(innerEncoder,
                                                  ToBackend(cmd->querySet)->GetInnerHandle(),
                                                  uint32_t{cmd->queryIndex});
                break;
            }
            case Command::InsertDebugMarker: {
                auto cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
                std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
                wgpu.commandEncoderInsertDebugMarker(innerEncoder, {label.data(), label.size()});
                break;
            }
            case Command::PopDebugGroup: {
                mCommands.NextCommand<PopDebugGroupCmd>();
                wgpu.commandEncoderPopDebugGroup(innerEncoder);
                break;
            }
            case Command::PushDebugGroup: {
                auto cmd = mCommands.NextCommand<PushDebugGroupCmd>();
                std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
                wgpu.commandEncoderPushDebugGroup(innerEncoder, {label.data(), label.size()});
                break;
            }
            case Command::WriteBuffer: {
                auto cmd = mCommands.NextCommand<WriteBufferCmd>();
                Span<const uint8_t> data = mCommands.NextData<uint8_t>(cmd->size);
                wgpu.commandEncoderWriteBuffer(innerEncoder,
                                               ToBackend(cmd->buffer)->GetInnerHandle(),
                                               cmd->offset, data.data(), data.size());
                break;
            }
            default:
                DAWN_UNREACHABLE();
        }
    }

    // TODO(crbug.com/413053623): Store WGPUCommandBufferDescriptor and assign here.
    WGPUCommandBuffer result = wgpu.commandEncoderFinish(innerEncoder, nullptr);
    wgpu.commandEncoderRelease(innerEncoder);
    return result;
}

}  // namespace dawn::native::webgpu
