// 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 "dawn/replay/Replay.h"

#include <webgpu/webgpu_cpp.h>
#include <algorithm>
#include <iostream>
#include <memory>
#include <ranges>
#include <string>
#include <utility>
#include <variant>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "dawn/common/Constants.h"
#include "dawn/replay/Capture.h"
#include "dawn/replay/Deserialization.h"
#include "src/dawn/replay/ReplayImpl.h"

namespace dawn::replay {

Replay::~Replay() = default;

std::unique_ptr<Replay> Replay::Create(wgpu::Device device, std::unique_ptr<Capture> capture) {
    return ReplayImpl::Create(device, std::move(capture));
}

template <typename T>
T Replay::GetObjectByLabel(std::string_view label) const {
    if (auto* impl = static_cast<const ReplayImpl*>(this)) {
        return impl->GetObjectByLabel<T>(label);
    }
    return nullptr;
}

bool Replay::Play() {
    if (auto* impl = static_cast<ReplayImpl*>(this)) {
        auto result = impl->Play();
        return result.IsSuccess();
    }
    return false;
}

template wgpu::BindGroup Replay::GetObjectByLabel<wgpu::BindGroup>(std::string_view label) const;
template wgpu::BindGroupLayout Replay::GetObjectByLabel<wgpu::BindGroupLayout>(
    std::string_view label) const;
template wgpu::Buffer Replay::GetObjectByLabel<wgpu::Buffer>(std::string_view label) const;
template wgpu::CommandBuffer Replay::GetObjectByLabel<wgpu::CommandBuffer>(
    std::string_view label) const;
template wgpu::ComputePipeline Replay::GetObjectByLabel<wgpu::ComputePipeline>(
    std::string_view label) const;
template wgpu::Device Replay::GetObjectByLabel<wgpu::Device>(std::string_view label) const;
template wgpu::PipelineLayout Replay::GetObjectByLabel<wgpu::PipelineLayout>(
    std::string_view label) const;
template wgpu::QuerySet Replay::GetObjectByLabel<wgpu::QuerySet>(std::string_view label) const;
template wgpu::RenderBundle Replay::GetObjectByLabel<wgpu::RenderBundle>(
    std::string_view label) const;
template wgpu::RenderPipeline Replay::GetObjectByLabel<wgpu::RenderPipeline>(
    std::string_view label) const;
template wgpu::Sampler Replay::GetObjectByLabel<wgpu::Sampler>(std::string_view label) const;
template wgpu::ShaderModule Replay::GetObjectByLabel<wgpu::ShaderModule>(
    std::string_view label) const;
template wgpu::Texture Replay::GetObjectByLabel<wgpu::Texture>(std::string_view label) const;
template wgpu::TextureView Replay::GetObjectByLabel<wgpu::TextureView>(
    std::string_view label) const;

namespace {

wgpu::Origin3D ToWGPU(const schema::Origin3D& origin) {
    return wgpu::Origin3D{
        .x = origin.x,
        .y = origin.y,
        .z = origin.z,
    };
}

wgpu::Extent3D ToWGPU(const schema::Extent3D& extent) {
    return wgpu::Extent3D{
        .width = extent.width,
        .height = extent.height,
        .depthOrArrayLayers = extent.depthOrArrayLayers,
    };
}

wgpu::Color ToWGPU(const schema::Color& color) {
    return wgpu::Color{
        .r = color.r,
        .g = color.g,
        .b = color.b,
        .a = color.a,
    };
}

wgpu::PassTimestampWrites ToWGPU(const ReplayImpl& replay, const schema::TimestampWrites& writes) {
    return wgpu::PassTimestampWrites{
        .nextInChain = nullptr,
        .querySet = replay.GetObjectById<wgpu::QuerySet>(writes.querySetId),
        .beginningOfPassWriteIndex = writes.beginningOfPassWriteIndex,
        .endOfPassWriteIndex = writes.endOfPassWriteIndex,
    };
}

std::vector<wgpu::ConstantEntry> ToWGPU(const std::vector<schema::PipelineConstant>& constants) {
    std::vector<wgpu::ConstantEntry> entries;
    entries.reserve(constants.size());
    std::transform(constants.begin(), constants.end(), std::back_inserter(entries),
                   [](const auto& constant) {
                       return wgpu::ConstantEntry{
                           .key = wgpu::StringView(constant.name),
                           .value = constant.value,
                       };
                   });
    return entries;
}

wgpu::TexelCopyBufferLayout ToWGPU(const schema::TexelCopyBufferLayout& info) {
    return wgpu::TexelCopyBufferLayout{
        .offset = info.offset,
        .bytesPerRow = info.bytesPerRow,
        .rowsPerImage = info.rowsPerImage,
    };
}

wgpu::TexelCopyBufferInfo ToWGPU(const ReplayImpl& replay,
                                 const schema::TexelCopyBufferInfo& info) {
    return wgpu::TexelCopyBufferInfo{
        .layout = ToWGPU(info.layout),
        .buffer = replay.GetObjectById<wgpu::Buffer>(info.bufferId),
    };
}

wgpu::TexelCopyTextureInfo ToWGPU(const ReplayImpl& replay,
                                  const schema::TexelCopyTextureInfo& info) {
    return wgpu::TexelCopyTextureInfo{
        .texture = replay.GetObjectById<wgpu::Texture>(info.textureId),
        .mipLevel = info.mipLevel,
        .origin = ToWGPU(info.origin),
        .aspect = static_cast<wgpu::TextureAspect>(info.aspect),
    };
}

wgpu::StencilFaceState ToWGPU(const schema::StencilFaceState& state) {
    return wgpu::StencilFaceState{
        .compare = state.compare,
        .failOp = state.failOp,
        .depthFailOp = state.depthFailOp,
        .passOp = state.passOp,
    };
}

wgpu::BlendComponent ToWGPU(const schema::BlendComponent& component) {
    return wgpu::BlendComponent{
        .operation = component.operation,
        .srcFactor = component.srcFactor,
        .dstFactor = component.dstFactor,
    };
}

wgpu::BlendState ToWGPU(const schema::BlendState& state) {
    return wgpu::BlendState{
        .color = ToWGPU(state.color),
        .alpha = ToWGPU(state.alpha),
    };
}

bool IsBlendComponentEnabled(const wgpu::BlendComponent& component) {
    return component.operation != wgpu::BlendOperation::Add ||
           component.srcFactor != wgpu::BlendFactor::One ||
           component.dstFactor != wgpu::BlendFactor::Zero;
}

bool IsBlendEnabled(const wgpu::BlendState& blend) {
    return IsBlendComponentEnabled(blend.color) || IsBlendComponentEnabled(blend.alpha);
}

MaybeError ReadContentIntoBuffer(ReadHead& readHead,
                                 wgpu::Device device,
                                 wgpu::Buffer buffer,
                                 uint64_t bufferOffset,
                                 uint64_t size) {
    const uint32_t* data;
    DAWN_TRY_ASSIGN(data, readHead.GetData(size));

    device.GetQueue().WriteBuffer(buffer, bufferOffset, data, size);
    return {};
}

MaybeError MapContentIntoBuffer(ReadHead& readHead,
                                wgpu::Device device,
                                wgpu::Buffer buffer,
                                uint64_t bufferOffset,
                                uint64_t size) {
    const uint32_t* data;
    DAWN_TRY_ASSIGN(data, readHead.GetData(size));

    // Note: We could call MapAsync here, wait for it to map, put in the data, then unmap.
    // To do so we'd have to change the code in ReplayImpl::CreateBuffer to leave the buffer
    // as MapWrite|CopySrc. That would be more inline with what the user actually did
    // though it might be slower as it would be synchronous.
    device.GetQueue().WriteBuffer(buffer, bufferOffset, data, size);
    return {};
}

MaybeError ReadContentIntoTexture(const ReplayImpl& replay,
                                  ReadHead& readHead,
                                  wgpu::Device device,
                                  const schema::RootCommandWriteTextureCmdData& cmdData) {
    const uint64_t dataSize = (cmdData.dataSize + 3) & ~3;

    const uint32_t* data;
    DAWN_TRY_ASSIGN(data, readHead.GetData(dataSize));

    wgpu::TexelCopyTextureInfo dst = ToWGPU(replay, cmdData.destination);
    wgpu::TexelCopyBufferLayout layout = ToWGPU(cmdData.layout);
    wgpu::Extent3D size = ToWGPU(cmdData.size);
    device.GetQueue().WriteTexture(&dst, data, cmdData.dataSize, &layout, &size);
    return {};
}

ResultOrError<wgpu::BindGroup> CreateBindGroup(const ReplayImpl& replay,
                                               wgpu::Device device,
                                               ReadHead& readHead,
                                               const std::string& label) {
    schema::BindGroup bg;
    DAWN_TRY(Deserialize(readHead, &bg));

    std::vector<wgpu::BindGroupEntry> entries;
    for (uint32_t i = 0; i < bg.numEntries; ++i) {
        schema::BindGroupLayoutEntryType entryType;
        uint32_t binding;
        DAWN_TRY(Deserialize(readHead, &entryType));
        DAWN_TRY(Deserialize(readHead, &binding));

        switch (entryType) {
            case schema::BindGroupLayoutEntryType::BufferBinding: {
                schema::BindGroupEntryTypeBufferBindingData data;
                DAWN_TRY(Deserialize(readHead, &data));
                entries.push_back(wgpu::BindGroupEntry{
                    .binding = binding,
                    .buffer = replay.GetObjectById<wgpu::Buffer>(data.bufferId),
                    .offset = data.offset,
                    .size = data.size,
                });
                break;
            }
            case schema::BindGroupLayoutEntryType::SamplerBinding: {
                schema::BindGroupEntryTypeSamplerBindingData data;
                DAWN_TRY(Deserialize(readHead, &data));
                entries.push_back(wgpu::BindGroupEntry{
                    .binding = binding,
                    .sampler = replay.GetObjectById<wgpu::Sampler>(data.samplerId),
                });
                break;
            }
            case schema::BindGroupLayoutEntryType::TextureBinding: {
                schema::BindGroupEntryTypeTextureBindingData data;
                DAWN_TRY(Deserialize(readHead, &data));
                entries.push_back(wgpu::BindGroupEntry{
                    .binding = binding,
                    .textureView = replay.GetObjectById<wgpu::TextureView>(data.textureViewId),
                });
                break;
            }
            default:
                return DAWN_INTERNAL_ERROR("unsupported bind group entry type");
        }
    }

    wgpu::BindGroupDescriptor desc{
        .label = wgpu::StringView(label),
        .layout = replay.GetObjectById<wgpu::BindGroupLayout>(bg.layoutId),
        .entryCount = entries.size(),
        .entries = entries.data(),
    };
    wgpu::BindGroup bindGroup = device.CreateBindGroup(&desc);
    return {bindGroup};
}

ResultOrError<wgpu::BindGroupLayout> CreateBindGroupLayout(const ReplayImpl& replay,
                                                           wgpu::Device device,
                                                           ReadHead& readHead,
                                                           const std::string& label) {
    schema::BindGroupLayout bgl;
    DAWN_TRY(Deserialize(readHead, &bgl));

    std::vector<wgpu::BindGroupLayoutEntry> entries;
    for (uint32_t i = 0; i < bgl.numEntries; ++i) {
        schema::BindGroupLayoutEntryType entryType;
        schema::BindGroupLayoutBinding binding;
        DAWN_TRY(Deserialize(readHead, &entryType));
        DAWN_TRY(Deserialize(readHead, &binding));

        switch (entryType) {
            case schema::BindGroupLayoutEntryType::BufferBinding: {
                schema::BindGroupLayoutEntryTypeBufferBindingData data;
                DAWN_TRY(Deserialize(readHead, &data));

                entries.push_back({
                    .binding = binding.binding,
                    .visibility = binding.visibility,
                    .bindingArraySize = binding.bindingArraySize,
                    .buffer =
                        {
                            .type = data.type,
                            .hasDynamicOffset = data.hasDynamicOffset,
                            .minBindingSize = data.minBindingSize,
                        },
                });
                break;
            }
            case schema::BindGroupLayoutEntryType::SamplerBinding: {
                schema::BindGroupLayoutEntryTypeSamplerBindingData data;
                DAWN_TRY(Deserialize(readHead, &data));

                entries.push_back({
                    .binding = binding.binding,
                    .visibility = binding.visibility,
                    .bindingArraySize = binding.bindingArraySize,
                    .sampler =
                        {
                            .type = data.type,
                        },
                });
                break;
            }
            case schema::BindGroupLayoutEntryType::StorageTextureBinding: {
                schema::BindGroupLayoutEntryTypeStorageTextureBindingData data;
                DAWN_TRY(Deserialize(readHead, &data));

                entries.push_back({
                    .binding = binding.binding,
                    .visibility = binding.visibility,
                    .bindingArraySize = binding.bindingArraySize,
                    .storageTexture =
                        {
                            .access = data.access,
                            .format = data.format,
                            .viewDimension = data.viewDimension,
                        },
                });
                break;
            }
            case schema::BindGroupLayoutEntryType::TextureBinding: {
                schema::BindGroupLayoutEntryTypeTextureBindingData data;
                DAWN_TRY(Deserialize(readHead, &data));

                entries.push_back({
                    .binding = binding.binding,
                    .visibility = binding.visibility,
                    .bindingArraySize = binding.bindingArraySize,
                    .texture =
                        {
                            .sampleType = data.sampleType,
                            .viewDimension = data.viewDimension,
                            .multisampled = data.multisampled,
                        },
                });
                break;
            }
            default:
                return DAWN_INTERNAL_ERROR("unhandled bind group layout entry type");
        }
    }

    wgpu::BindGroupLayoutDescriptor desc{
        .label = wgpu::StringView(label),
        .entryCount = entries.size(),
        .entries = entries.data(),
    };
    wgpu::BindGroupLayout bindGroupLayout = device.CreateBindGroupLayout(&desc);
    return {bindGroupLayout};
}

ResultOrError<wgpu::Buffer> CreateBuffer(wgpu::Device device,
                                         ReadHead& readHead,
                                         const std::string& label) {
    schema::Buffer buf;
    DAWN_TRY(Deserialize(readHead, &buf));

    wgpu::BufferUsage usage =
        (buf.usage & (wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite))
            ? buf.usage
            : (buf.usage | wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);

    // Remap mappable write buffers as CopySrc|CopyDst as we use WriteBuffer to set their contents.
    if (usage == (wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc)) {
        usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
    }

    wgpu::BufferDescriptor desc{
        .label = wgpu::StringView(label),
        .usage = usage,
        .size = buf.size,
    };
    wgpu::Buffer buffer = device.CreateBuffer(&desc);
    return {buffer};
}

ResultOrError<wgpu::ComputePipeline> CreateComputePipeline(const ReplayImpl& replay,
                                                           wgpu::Device device,
                                                           ReadHead& readHead,
                                                           const std::string& label) {
    schema::ComputePipeline pipeline;
    DAWN_TRY(Deserialize(readHead, &pipeline));

    std::vector<wgpu::ConstantEntry> constants = ToWGPU(pipeline.compute.constants);

    wgpu::ComputePipelineDescriptor desc{
        .label = wgpu::StringView(label),
        .layout = replay.GetObjectById<wgpu::PipelineLayout>(pipeline.layoutId),
        .compute =
            {
                .module = replay.GetObjectById<wgpu::ShaderModule>(pipeline.compute.moduleId),
                .entryPoint = wgpu::StringView(pipeline.compute.entryPoint),
                .constantCount = constants.size(),
                .constants = constants.data(),
            },
    };
    wgpu::ComputePipeline computePipeline = device.CreateComputePipeline(&desc);
    return {computePipeline};
}

ResultOrError<wgpu::PipelineLayout> CreatePipelineLayout(const ReplayImpl& replay,
                                                         wgpu::Device device,
                                                         ReadHead& readHead,
                                                         const std::string& label) {
    schema::PipelineLayout layout;
    DAWN_TRY(Deserialize(readHead, &layout));

    std::vector<wgpu::BindGroupLayout> bindGroupLayouts;
    for (const auto bindGroupLayoutId : layout.bindGroupLayoutIds) {
        bindGroupLayouts.push_back(replay.GetObjectById<wgpu::BindGroupLayout>(bindGroupLayoutId));
    }

    wgpu::PipelineLayoutDescriptor desc{
        .label = wgpu::StringView(label),
        .bindGroupLayoutCount = bindGroupLayouts.size(),
        .bindGroupLayouts = bindGroupLayouts.data(),
        .immediateSize = layout.immediateSize,
    };
    wgpu::PipelineLayout pipelineLayout = device.CreatePipelineLayout(&desc);
    return {pipelineLayout};
}

ResultOrError<wgpu::QuerySet> CreateQuerySet(const ReplayImpl& replay,
                                             wgpu::Device device,
                                             ReadHead& readHead,
                                             const std::string& label) {
    schema::QuerySet querySetData;
    DAWN_TRY(Deserialize(readHead, &querySetData));

    wgpu::QuerySetDescriptor desc{
        .label = wgpu::StringView(label),
        .type = querySetData.type,
        .count = querySetData.count,
    };
    wgpu::QuerySet querySet = device.CreateQuerySet(&desc);
    return {querySet};
}

template <typename T>
MaybeError ProcessWriteTimestamp(const ReplayImpl& replay, T pass, ReadHead& readHead) {
    schema::CommandBufferCommandWriteTimestampCmdData data;
    DAWN_TRY(Deserialize(readHead, &data));
    pass.WriteTimestamp(replay.GetObjectById<wgpu::QuerySet>(data.querySetId), data.queryIndex);
    return {};
}

template <typename T>
MaybeError ProcessSharedCommands(const ReplayImpl& replay,
                                 T pass,
                                 schema::CommandBufferCommand cmd,
                                 ReadHead& readHead) {
    switch (cmd) {
        case schema::CommandBufferCommand::SetBindGroup: {
            schema::CommandBufferCommandSetBindGroupCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.SetBindGroup(data.index, replay.GetObjectById<wgpu::BindGroup>(data.bindGroupId),
                              data.dynamicOffsets.size(), data.dynamicOffsets.data());
            break;
        }
        case schema::CommandBufferCommand::SetImmediates: {
            schema::CommandBufferCommandSetImmediatesCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.SetImmediates(data.offset, data.data.data(), data.data.size());
            break;
        }
        default:
            DAWN_UNREACHABLE();
    }
    return {};
}

template <typename T>
MaybeError ProcessDebugCommands(T pass, schema::CommandBufferCommand cmd, ReadHead& readHead) {
    switch (cmd) {
        case schema::CommandBufferCommand::PushDebugGroup: {
            schema::CommandBufferCommandPushDebugGroupCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.PushDebugGroup(wgpu::StringView(data.groupLabel));
            break;
        }
        case schema::CommandBufferCommand::InsertDebugMarker: {
            schema::CommandBufferCommandInsertDebugMarkerCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.InsertDebugMarker(wgpu::StringView(data.markerLabel));
            break;
        }
        case schema::CommandBufferCommand::PopDebugGroup: {
            // PopDebugGroup has no data
            pass.PopDebugGroup();
            break;
        }
        default:
            DAWN_UNREACHABLE();
    }
    return {};
}

template <typename T>
MaybeError ProcessRenderCommand(const ReplayImpl& replay,
                                ReadHead& readHead,
                                wgpu::Device device,
                                schema::CommandBufferCommand cmd,
                                T pass) {
    switch (cmd) {
        case schema::CommandBufferCommand::SetRenderPipeline: {
            schema::CommandBufferCommandSetRenderPipelineCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.SetPipeline(replay.GetObjectById<wgpu::RenderPipeline>(data.pipelineId));
            break;
        }
        case schema::CommandBufferCommand::SetVertexBuffer: {
            schema::CommandBufferCommandSetVertexBufferCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.SetVertexBuffer(data.slot, replay.GetObjectById<wgpu::Buffer>(data.bufferId),
                                 data.offset, data.size);
            break;
        }
        case schema::CommandBufferCommand::SetIndexBuffer: {
            schema::CommandBufferCommandSetIndexBufferCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.SetIndexBuffer(replay.GetObjectById<wgpu::Buffer>(data.bufferId), data.format,
                                data.offset, data.size);
            break;
        }
        case schema::CommandBufferCommand::Draw: {
            schema::CommandBufferCommandDrawCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.Draw(data.vertexCount, data.instanceCount, data.firstVertex, data.firstInstance);
            break;
        }
        case schema::CommandBufferCommand::DrawIndexed: {
            schema::CommandBufferCommandDrawIndexedCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.DrawIndexed(data.indexCount, data.instanceCount, data.firstIndex, data.baseVertex,
                             data.firstInstance);
            break;
        }
        case schema::CommandBufferCommand::DrawIndirect: {
            schema::CommandBufferCommandDrawIndirectCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.DrawIndirect(replay.GetObjectById<wgpu::Buffer>(data.indirectBufferId),
                              data.indirectOffset);
            break;
        }
        case schema::CommandBufferCommand::DrawIndexedIndirect: {
            schema::CommandBufferCommandDrawIndexedIndirectCmdData data;
            DAWN_TRY(Deserialize(readHead, &data));
            pass.DrawIndexedIndirect(replay.GetObjectById<wgpu::Buffer>(data.indirectBufferId),
                                     data.indirectOffset);
            break;
        }
        case schema::CommandBufferCommand::SetBindGroup:
        case schema::CommandBufferCommand::SetImmediates:
            DAWN_TRY(ProcessSharedCommands(replay, pass, cmd, readHead));
            break;
        case schema::CommandBufferCommand::PushDebugGroup:
        case schema::CommandBufferCommand::InsertDebugMarker:
        case schema::CommandBufferCommand::PopDebugGroup:
            DAWN_TRY(ProcessDebugCommands(pass, cmd, readHead));
            break;
        default:
            return DAWN_INTERNAL_ERROR("Render Pass/Bundle Command not implemented");
    }
    return {};
}

MaybeError ProcessRenderBundleCommands(const ReplayImpl& replay,
                                       ReadHead& readHead,
                                       wgpu::Device device,
                                       wgpu::RenderBundleEncoder pass) {
    schema::CommandBufferCommand cmd;

    while (!readHead.IsDone()) {
        DAWN_TRY(Deserialize(readHead, &cmd));
        switch (cmd) {
            case schema::CommandBufferCommand::End: {
                return {};
            }
            default:
                DAWN_TRY(ProcessRenderCommand(replay, readHead, device, cmd, pass));
                break;
        }
    }
    return DAWN_INTERNAL_ERROR("Missing RenderBundle End command");
}

ResultOrError<wgpu::RenderBundle> CreateRenderBundle(const ReplayImpl& replay,
                                                     wgpu::Device device,
                                                     ReadHead& readHead,
                                                     const std::string& label) {
    schema::RenderBundle bundle;
    DAWN_TRY(Deserialize(readHead, &bundle));

    wgpu::RenderBundleEncoderDescriptor desc{
        .colorFormatCount = bundle.colorFormats.size(),
        .colorFormats = bundle.colorFormats.data(),
        .depthStencilFormat = bundle.depthStencilFormat,
        .sampleCount = bundle.sampleCount,
        .depthReadOnly = bundle.depthReadOnly,
        .stencilReadOnly = bundle.stencilReadOnly,
    };
    wgpu::RenderBundleEncoder encoder = device.CreateRenderBundleEncoder(&desc);
    DAWN_TRY(ProcessRenderBundleCommands(replay, readHead, device, encoder));

    wgpu::RenderBundleDescriptor bundleDesc{
        .label = wgpu::StringView(label),
    };
    wgpu::RenderBundle renderBundle = encoder.Finish(&bundleDesc);
    return {renderBundle};
}

ResultOrError<wgpu::RenderPipeline> CreateRenderPipeline(const ReplayImpl& replay,
                                                         wgpu::Device device,
                                                         ReadHead& readHead,
                                                         const std::string& label) {
    schema::RenderPipeline pipeline;
    DAWN_TRY(Deserialize(readHead, &pipeline));

    std::vector<wgpu::ConstantEntry> vertexConstants = ToWGPU(pipeline.vertex.program.constants);
    std::vector<wgpu::ConstantEntry> fragmentConstants =
        ToWGPU(pipeline.fragment.program.constants);
    std::vector<wgpu::ColorTargetState> colorTargets;
    std::vector<wgpu::BlendState> blendStates(pipeline.fragment.targets.size());
    std::vector<wgpu::VertexBufferLayout> buffers;

    std::vector<wgpu::VertexAttribute> attributes(kMaxVertexAttributes);
    uint32_t attributeCount = 0;

    for (const auto& buffer : pipeline.vertex.buffers) {
        const auto attributesForBuffer = &attributes[attributeCount];
        for (const auto& attrib : buffer.attributes) {
            auto& attr = attributes[attributeCount++];
            attr.format = attrib.format;
            attr.offset = attrib.offset;
            attr.shaderLocation = attrib.shaderLocation;
        }
        buffers.push_back({
            .stepMode = buffer.stepMode,
            .arrayStride = buffer.arrayStride,
            .attributeCount = buffer.attributes.size(),
            .attributes = attributesForBuffer,
        });
    }

    wgpu::FragmentState* fragment = nullptr;
    wgpu::FragmentState fragmentState;
    if (pipeline.fragment.program.moduleId) {
        fragment = &fragmentState;
        fragmentState.module =
            replay.GetObjectById<wgpu::ShaderModule>(pipeline.fragment.program.moduleId);
        fragmentState.entryPoint = wgpu::StringView(pipeline.fragment.program.entryPoint);
        fragmentState.constantCount = fragmentConstants.size();
        fragmentState.constants = fragmentConstants.data();
        for (const auto& target : pipeline.fragment.targets) {
            wgpu::BlendState& blend = blendStates[colorTargets.size()];
            blend = ToWGPU(target.blend);
            colorTargets.push_back({
                .format = target.format,
                .blend = IsBlendEnabled(blend) ? &blend : nullptr,
                .writeMask = target.writeMask,
            });
        }
        fragmentState.targetCount = colorTargets.size();
        fragmentState.targets = colorTargets.data();
    }

    wgpu::DepthStencilState* depthStencil = nullptr;
    wgpu::DepthStencilState depthStencilState;
    if (pipeline.depthStencil.format != wgpu::TextureFormat::Undefined) {
        depthStencil = &depthStencilState;
        depthStencilState.format = pipeline.depthStencil.format;
        depthStencilState.depthWriteEnabled = pipeline.depthStencil.depthWriteEnabled;
        depthStencilState.depthCompare = pipeline.depthStencil.depthCompare;
        depthStencilState.stencilFront = ToWGPU(pipeline.depthStencil.stencilFront);
        depthStencilState.stencilBack = ToWGPU(pipeline.depthStencil.stencilBack);
        depthStencilState.stencilReadMask = pipeline.depthStencil.stencilReadMask;
        depthStencilState.stencilWriteMask = pipeline.depthStencil.stencilWriteMask;
        depthStencilState.depthBias = pipeline.depthStencil.depthBias;
        depthStencilState.depthBiasSlopeScale = pipeline.depthStencil.depthBiasSlopeScale;
        depthStencilState.depthBiasClamp = pipeline.depthStencil.depthBiasClamp;
    }

    wgpu::RenderPipelineDescriptor desc{
        .label = wgpu::StringView(label),
        .layout = replay.GetObjectById<wgpu::PipelineLayout>(pipeline.layoutId),
        .vertex =
            {
                .module =
                    replay.GetObjectById<wgpu::ShaderModule>(pipeline.vertex.program.moduleId),
                .entryPoint = wgpu::StringView(pipeline.vertex.program.entryPoint),
                .constantCount = vertexConstants.size(),
                .constants = vertexConstants.data(),
                .bufferCount = buffers.size(),
                .buffers = buffers.data(),
            },
        .primitive =
            {
                .topology = pipeline.primitive.topology,
                .stripIndexFormat = pipeline.primitive.stripIndexFormat,
                .frontFace = pipeline.primitive.frontFace,
                .cullMode = pipeline.primitive.cullMode,
                .unclippedDepth = pipeline.primitive.unclippedDepth,
            },
        .depthStencil = depthStencil,
        .multisample =
            {
                .count = pipeline.multisample.count,
                .mask = pipeline.multisample.mask,
                .alphaToCoverageEnabled = pipeline.multisample.alphaToCoverageEnabled,
            },
        .fragment = fragment,
    };
    wgpu::RenderPipeline renderPipeline = device.CreateRenderPipeline(&desc);
    return {renderPipeline};
}

ResultOrError<wgpu::Sampler> CreateSampler(wgpu::Device device,
                                           ReadHead& readHead,
                                           const std::string& label) {
    schema::Sampler sampler;
    DAWN_TRY(Deserialize(readHead, &sampler));

    wgpu::SamplerDescriptor desc{
        .label = wgpu::StringView(label),
        .addressModeU = sampler.addressModeU,
        .addressModeV = sampler.addressModeV,
        .addressModeW = sampler.addressModeW,
        .magFilter = sampler.magFilter,
        .minFilter = sampler.minFilter,
        .mipmapFilter = sampler.mipmapFilter,
        .lodMinClamp = sampler.lodMinClamp,
        .lodMaxClamp = sampler.lodMaxClamp,
        .compare = sampler.compare,
        .maxAnisotropy = sampler.maxAnisotropy,
    };
    return {device.CreateSampler(&desc)};
}

ResultOrError<wgpu::ShaderModule> CreateShaderModule(wgpu::Device device,
                                                     ReadHead& readHead,
                                                     const std::string& label) {
    schema::ShaderModule mod;
    DAWN_TRY(Deserialize(readHead, &mod));

    // TODO(452840621): Make this use a chain instead of hard coded to WGSL only and handle other
    // chained structs.
    wgpu::ShaderSourceWGSL source({
        .nextInChain = nullptr,
        .code = wgpu::StringView(mod.code),
    });
    wgpu::ShaderModuleDescriptor desc{
        .nextInChain = &source,
        .label = wgpu::StringView(label),
    };
    wgpu::ShaderModule shaderModule = device.CreateShaderModule(&desc);
    return {shaderModule};
}

ResultOrError<wgpu::Texture> CreateTexture(wgpu::Device device,
                                           ReadHead& readHead,
                                           const std::string& label) {
    schema::Texture tex;
    DAWN_TRY(Deserialize(readHead, &tex));

    wgpu::TextureDescriptor desc{
        .label = wgpu::StringView(label),
        .usage = tex.usage | wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst,
        .dimension = tex.dimension,
        .size = ToWGPU(tex.size),
        .format = tex.format,
        .mipLevelCount = tex.mipLevelCount,
        .sampleCount = tex.sampleCount,
        .viewFormatCount = tex.viewFormats.size(),
        .viewFormats = tex.viewFormats.data(),
    };
    wgpu::Texture texture = device.CreateTexture(&desc);
    return {texture};
}

ResultOrError<wgpu::TextureView> CreateTextureView(const ReplayImpl& replay,
                                                   ReadHead& readHead,
                                                   const std::string& label) {
    schema::TextureView view;
    DAWN_TRY(Deserialize(readHead, &view));

    wgpu::TextureViewDescriptor desc{
        .label = wgpu::StringView(label),
        .format = view.format,
        .dimension = view.dimension,
        .baseMipLevel = view.baseMipLevel,
        .mipLevelCount = view.mipLevelCount,
        .baseArrayLayer = view.baseArrayLayer,
        .arrayLayerCount = view.arrayLayerCount,
        .aspect = view.aspect,
        .usage = view.usage,
    };
    wgpu::Texture texture = replay.GetObjectById<wgpu::Texture>(view.textureId);
    wgpu::TextureView textureView = texture.CreateView(&desc);
    return {textureView};
}

MaybeError ProcessComputePassCommands(const ReplayImpl& replay,
                                      ReadHead& readHead,
                                      wgpu::Device device,
                                      wgpu::ComputePassEncoder pass) {
    schema::CommandBufferCommand cmd;

    while (!readHead.IsDone()) {
        DAWN_TRY(Deserialize(readHead, &cmd));
        switch (cmd) {
            case schema::CommandBufferCommand::End: {
                pass.End();
                return {};
            }
            case schema::CommandBufferCommand::SetComputePipeline: {
                schema::CommandBufferCommandSetComputePipelineCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                pass.SetPipeline(replay.GetObjectById<wgpu::ComputePipeline>(data.pipelineId));
                break;
            }
            case schema::CommandBufferCommand::Dispatch: {
                schema::CommandBufferCommandDispatchCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                pass.DispatchWorkgroups(data.x, data.y, data.z);
                break;
            }
            case schema::CommandBufferCommand::DispatchIndirect: {
                schema::CommandBufferCommandDispatchIndirectCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                pass.DispatchWorkgroupsIndirect(replay.GetObjectById<wgpu::Buffer>(data.bufferId),
                                                data.offset);
                break;
            }
            case schema::CommandBufferCommand::WriteTimestamp:
                DAWN_TRY(ProcessWriteTimestamp(replay, pass, readHead));
                break;
            case schema::CommandBufferCommand::SetBindGroup:
            case schema::CommandBufferCommand::SetImmediates:
                DAWN_TRY(ProcessSharedCommands(replay, pass, cmd, readHead));
                break;
            case schema::CommandBufferCommand::PushDebugGroup:
            case schema::CommandBufferCommand::InsertDebugMarker:
            case schema::CommandBufferCommand::PopDebugGroup:
                DAWN_TRY(ProcessDebugCommands(pass, cmd, readHead));
                break;
            default:
                return DAWN_INTERNAL_ERROR("Compute Pass Command not implemented");
        }
    }
    return DAWN_INTERNAL_ERROR("Missing ComputePass End command");
}

MaybeError ProcessRenderPassCommands(const ReplayImpl& replay,
                                     ReadHead& readHead,
                                     wgpu::Device device,
                                     wgpu::RenderPassEncoder pass) {
    schema::CommandBufferCommand cmd;

    while (!readHead.IsDone()) {
        DAWN_TRY(Deserialize(readHead, &cmd));
        switch (cmd) {
            case schema::CommandBufferCommand::End: {
                pass.End();
                return {};
            }
            case schema::CommandBufferCommand::ExecuteBundles: {
                schema::CommandBufferCommandExecuteBundlesCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                std::vector<wgpu::RenderBundle> bundles;
                for (auto bundleId : data.bundleIds) {
                    bundles.push_back(replay.GetObjectById<wgpu::RenderBundle>(bundleId));
                }
                pass.ExecuteBundles(bundles.size(), bundles.data());
                break;
            }
            case schema::CommandBufferCommand::BeginOcclusionQuery: {
                schema::CommandBufferCommandBeginOcclusionQueryCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                pass.BeginOcclusionQuery(data.queryIndex);
                break;
            }
            case schema::CommandBufferCommand::EndOcclusionQuery: {
                pass.EndOcclusionQuery();
                break;
            }
            case schema::CommandBufferCommand::SetBlendConstant: {
                schema::CommandBufferCommandSetBlendConstantCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::Color color = ToWGPU(data.color);
                pass.SetBlendConstant(&color);
                break;
            }
            case schema::CommandBufferCommand::SetScissorRect: {
                schema::CommandBufferCommandSetScissorRectCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                pass.SetScissorRect(data.x, data.y, data.width, data.height);
                break;
            }
            case schema::CommandBufferCommand::SetStencilReference: {
                schema::CommandBufferCommandSetStencilReferenceCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                pass.SetStencilReference(data.reference);
                break;
            }
            case schema::CommandBufferCommand::SetViewport: {
                schema::CommandBufferCommandSetViewportCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                pass.SetViewport(data.x, data.y, data.width, data.height, data.minDepth,
                                 data.maxDepth);
                break;
            }
            case schema::CommandBufferCommand::WriteTimestamp:
                DAWN_TRY(ProcessWriteTimestamp(replay, pass, readHead));
                break;
            default:
                DAWN_TRY(ProcessRenderCommand(replay, readHead, device, cmd, pass));
                break;
        }
    }
    return DAWN_INTERNAL_ERROR("Missing RenderPass End command");
}

MaybeError ProcessEncoderCommands(const ReplayImpl& replay,
                                  ReadHead& readHead,
                                  wgpu::Device device,
                                  wgpu::CommandEncoder encoder) {
    schema::CommandBufferCommand cmd;

    while (!readHead.IsDone()) {
        DAWN_TRY(Deserialize(readHead, &cmd));
        switch (cmd) {
            case schema::CommandBufferCommand::BeginComputePass: {
                schema::CommandBufferCommandBeginComputePassCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::PassTimestampWrites timestampWrites = ToWGPU(replay, data.timestampWrites);
                wgpu::ComputePassDescriptor desc{
                    .label = wgpu::StringView(data.label),
                    .timestampWrites = timestampWrites.querySet ? &timestampWrites : nullptr,
                };
                wgpu::ComputePassEncoder pass = encoder.BeginComputePass(&desc);
                DAWN_TRY(ProcessComputePassCommands(replay, readHead, device, pass));
                break;
            }
            case schema::CommandBufferCommand::BeginRenderPass: {
                schema::CommandBufferCommandBeginRenderPassCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::PassTimestampWrites timestampWrites = ToWGPU(replay, data.timestampWrites);
                std::vector<wgpu::RenderPassColorAttachment> colorAttachments;

                for (const auto& attachment : data.colorAttachments) {
                    colorAttachments.push_back(wgpu::RenderPassColorAttachment{
                        .nextInChain = nullptr,
                        .view = replay.GetObjectById<wgpu::TextureView>(attachment.viewId),
                        .depthSlice = attachment.depthSlice,
                        .resolveTarget =
                            replay.GetObjectById<wgpu::TextureView>(attachment.resolveTargetId),
                        .loadOp = attachment.loadOp,
                        .storeOp = attachment.storeOp,
                        .clearValue = ToWGPU(attachment.clearValue),
                    });
                }

                wgpu::RenderPassDepthStencilAttachment depthStencilAttachment{
                    .view =
                        replay.GetObjectById<wgpu::TextureView>(data.depthStencilAttachment.viewId),
                    .depthLoadOp = data.depthStencilAttachment.depthLoadOp,
                    .depthStoreOp = data.depthStencilAttachment.depthStoreOp,
                    .depthClearValue = data.depthStencilAttachment.depthClearValue,
                    .depthReadOnly = data.depthStencilAttachment.depthReadOnly,
                    .stencilLoadOp = data.depthStencilAttachment.stencilLoadOp,
                    .stencilStoreOp = data.depthStencilAttachment.stencilStoreOp,
                    .stencilClearValue = data.depthStencilAttachment.stencilClearValue,
                    .stencilReadOnly = data.depthStencilAttachment.stencilReadOnly,
                };

                wgpu::RenderPassDescriptor desc{
                    .label = wgpu::StringView(data.label),
                    .colorAttachmentCount = colorAttachments.size(),
                    .colorAttachments = colorAttachments.data(),
                    .depthStencilAttachment =
                        depthStencilAttachment.view != nullptr ? &depthStencilAttachment : nullptr,
                    .occlusionQuerySet =
                        replay.GetObjectById<wgpu::QuerySet>(data.occlusionQuerySetId),
                    .timestampWrites = timestampWrites.querySet ? &timestampWrites : nullptr,
                };
                wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&desc);
                DAWN_TRY(ProcessRenderPassCommands(replay, readHead, device, pass));
                break;
            }
            case schema::CommandBufferCommand::ClearBuffer: {
                schema::CommandBufferCommandClearBufferCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                encoder.ClearBuffer(replay.GetObjectById<wgpu::Buffer>(data.bufferId), data.offset,
                                    data.size);
                break;
            }
            case schema::CommandBufferCommand::CopyBufferToBuffer: {
                schema::CommandBufferCommandCopyBufferToBufferCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                encoder.CopyBufferToBuffer(replay.GetObjectById<wgpu::Buffer>(data.srcBufferId),
                                           data.srcOffset,
                                           replay.GetObjectById<wgpu::Buffer>(data.dstBufferId),
                                           data.dstOffset, data.size);
                break;
            }
            case schema::CommandBufferCommand::CopyBufferToTexture: {
                schema::CommandBufferCommandCopyBufferToTextureCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::TexelCopyBufferInfo src = ToWGPU(replay, data.source);
                wgpu::TexelCopyTextureInfo dst = ToWGPU(replay, data.destination);
                wgpu::Extent3D copySize = ToWGPU(data.copySize);
                encoder.CopyBufferToTexture(&src, &dst, &copySize);
                break;
            }
            case schema::CommandBufferCommand::CopyTextureToBuffer: {
                schema::CommandBufferCommandCopyTextureToBufferCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::TexelCopyTextureInfo src = ToWGPU(replay, data.source);
                wgpu::TexelCopyBufferInfo dst = ToWGPU(replay, data.destination);
                wgpu::Extent3D copySize = ToWGPU(data.copySize);
                encoder.CopyTextureToBuffer(&src, &dst, &copySize);
                break;
            }
            case schema::CommandBufferCommand::CopyTextureToTexture: {
                schema::CommandBufferCommandCopyTextureToTextureCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::TexelCopyTextureInfo src = ToWGPU(replay, data.source);
                wgpu::TexelCopyTextureInfo dst = ToWGPU(replay, data.destination);
                wgpu::Extent3D copySize = ToWGPU(data.copySize);
                encoder.CopyTextureToTexture(&src, &dst, &copySize);
                break;
            }
            case schema::CommandBufferCommand::End: {
                return {};
            }
            case schema::CommandBufferCommand::ResolveQuerySet: {
                schema::CommandBufferCommandResolveQuerySetCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                encoder.ResolveQuerySet(replay.GetObjectById<wgpu::QuerySet>(data.querySetId),
                                        data.firstQuery, data.queryCount,
                                        replay.GetObjectById<wgpu::Buffer>(data.destinationId),
                                        data.destinationOffset);
                break;
            }
            case schema::CommandBufferCommand::WriteBuffer: {
                schema::CommandBufferCommandWriteBufferCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::Buffer buffer = replay.GetObjectById<wgpu::Buffer>(data.bufferId);
                encoder.WriteBuffer(buffer, data.bufferOffset, data.data.data(), data.data.size());
                break;
            }
            case schema::CommandBufferCommand::WriteTimestamp:
                DAWN_TRY(ProcessWriteTimestamp(replay, encoder, readHead));
                break;
            case schema::CommandBufferCommand::PushDebugGroup:
            case schema::CommandBufferCommand::InsertDebugMarker:
            case schema::CommandBufferCommand::PopDebugGroup:
                DAWN_TRY(ProcessDebugCommands(encoder, cmd, readHead));
                break;
            default:
                return DAWN_INTERNAL_ERROR("Encoder Command not implemented");
        }
    }
    return DAWN_INTERNAL_ERROR("Missing End command");
}

ResultOrError<wgpu::CommandBuffer> CreateCommandBuffer(const ReplayImpl& replay,
                                                       wgpu::Device device,
                                                       ReadHead& readHead,
                                                       const std::string& label) {
    wgpu::CommandEncoderDescriptor desc{
        .label = wgpu::StringView(label),
    };
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder(&desc);
    DAWN_TRY(ProcessEncoderCommands(replay, readHead, device, encoder));
    return {encoder.Finish()};
}

}  // anonymous namespace

std::unique_ptr<ReplayImpl> ReplayImpl::Create(wgpu::Device device,
                                               std::unique_ptr<Capture> capture) {
    auto captureImpl = std::unique_ptr<CaptureImpl>(static_cast<CaptureImpl*>(capture.release()));
    return std::unique_ptr<ReplayImpl>(new ReplayImpl(device, std::move(captureImpl)));
}

ReplayImpl::ReplayImpl(wgpu::Device device, std::unique_ptr<CaptureImpl> capture)
    : mDevice(device), mCapture(std::move(capture)) {
    mResources.insert({schema::kDeviceId, {"", device}});
}

MaybeError ReplayImpl::CreateResource(wgpu::Device device, ReadHead& readHead) {
    schema::LabeledResource resource;
    DAWN_TRY(Deserialize(readHead, &resource));

    switch (resource.type) {
        case schema::ObjectType::BindGroup: {
            wgpu::BindGroup bindGroup;
            DAWN_TRY_ASSIGN(bindGroup, CreateBindGroup(*this, device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, bindGroup}});
            return {};
        }

        case schema::ObjectType::BindGroupLayout: {
            wgpu::BindGroupLayout bindGroupLayout;
            DAWN_TRY_ASSIGN(bindGroupLayout,
                            CreateBindGroupLayout(*this, device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, bindGroupLayout}});
            return {};
        }

        case schema::ObjectType::Buffer: {
            wgpu::Buffer buffer;
            DAWN_TRY_ASSIGN(buffer, CreateBuffer(device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, buffer}});
            return {};
        }

        case schema::ObjectType::CommandBuffer: {
            // Command buffers are special and don't have any resources to create.
            // They are just a sequence of commands.
            wgpu::CommandBuffer commandBuffer;
            DAWN_TRY_ASSIGN(commandBuffer,
                            CreateCommandBuffer(*this, device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, commandBuffer}});
            return {};
        }

        case schema::ObjectType::ComputePipeline: {
            wgpu::ComputePipeline computePipeline;
            DAWN_TRY_ASSIGN(computePipeline,
                            CreateComputePipeline(*this, device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, computePipeline}});
            return {};
        }

        case schema::ObjectType::PipelineLayout: {
            wgpu::PipelineLayout pipelineLayout;
            DAWN_TRY_ASSIGN(pipelineLayout,
                            CreatePipelineLayout(*this, device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, pipelineLayout}});
            return {};
        }

        case schema::ObjectType::QuerySet: {
            wgpu::QuerySet querySet;
            DAWN_TRY_ASSIGN(querySet, CreateQuerySet(*this, device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, querySet}});
            return {};
        }

        case schema::ObjectType::RenderBundle: {
            // Command buffers are special and don't have any resources to create.
            // They are just a sequence of commands.
            wgpu::RenderBundle renderBundle;
            DAWN_TRY_ASSIGN(renderBundle,
                            CreateRenderBundle(*this, device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, renderBundle}});
            return {};
        }

        case schema::ObjectType::RenderPipeline: {
            wgpu::RenderPipeline renderPipeline;
            DAWN_TRY_ASSIGN(renderPipeline,
                            CreateRenderPipeline(*this, device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, renderPipeline}});
            return {};
        }

        case schema::ObjectType::Sampler: {
            wgpu::Sampler sampler;
            DAWN_TRY_ASSIGN(sampler, CreateSampler(device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, sampler}});
            return {};
        }

        case schema::ObjectType::ShaderModule: {
            wgpu::ShaderModule shaderModule;
            DAWN_TRY_ASSIGN(shaderModule, CreateShaderModule(device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, shaderModule}});
            return {};
        }

        case schema::ObjectType::Texture: {
            wgpu::Texture texture;
            DAWN_TRY_ASSIGN(texture, CreateTexture(device, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, texture}});
            return {};
        }

        case schema::ObjectType::TextureView: {
            wgpu::TextureView textureView;
            DAWN_TRY_ASSIGN(textureView, CreateTextureView(*this, readHead, resource.label));
            mResources.insert({resource.id, {resource.label, textureView}});
            return {};
        }

        default:
            return DAWN_INTERNAL_ERROR("unhandled resource type");
    }
}

MaybeError ReplayImpl::SetLabel(schema::ObjectId id,
                                schema::ObjectType type,
                                const std::string& label) {
// We update both the object's label and our own copy of the label
// as there is no API to get an object's label from WebGPU
#define DAWN_SET_LABEL(type)                                                                \
    case schema::ObjectType::type: {                                                        \
        auto iter = mResources.find(id);                                                    \
        std::get_if<wgpu::type>(&iter->second.resource)->SetLabel(wgpu::StringView(label)); \
        iter->second.label = label;                                                         \
        break;                                                                              \
    }

    switch (type) {
        DAWN_SET_LABEL(BindGroup)
        DAWN_SET_LABEL(BindGroupLayout)
        DAWN_SET_LABEL(Buffer)
        DAWN_SET_LABEL(CommandBuffer)
        DAWN_SET_LABEL(ComputePipeline)
        DAWN_SET_LABEL(Device)
        DAWN_SET_LABEL(PipelineLayout)
        DAWN_SET_LABEL(QuerySet)
        DAWN_SET_LABEL(RenderBundle)
        DAWN_SET_LABEL(RenderPipeline)
        DAWN_SET_LABEL(Sampler)
        DAWN_SET_LABEL(ShaderModule)
        DAWN_SET_LABEL(Texture)
        DAWN_SET_LABEL(TextureView)
        default:
            return DAWN_INTERNAL_ERROR("unhandled resource type");
    }
    return {};
}

MaybeError ReplayImpl::Play() {
    auto readHead = mCapture->GetCommandReadHead();
    auto contentReadHead = mCapture->GetContentReadHead();
    schema::RootCommand cmd;

    while (!readHead.IsDone()) {
        DAWN_TRY(Deserialize(readHead, &cmd));
        switch (cmd) {
            case schema::RootCommand::CreateResource: {
                DAWN_TRY(CreateResource(mDevice, readHead));
                break;
            }
            case schema::RootCommand::WriteBuffer: {
                schema::RootCommandWriteBufferCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::Buffer buffer = GetObjectById<wgpu::Buffer>(data.bufferId);
                DAWN_TRY(ReadContentIntoBuffer(contentReadHead, mDevice, buffer, data.bufferOffset,
                                               data.size));
                break;
            }
            case schema::RootCommand::WriteTexture: {
                // TODO(451460573): Support textures with multiple subresources
                schema::RootCommandWriteTextureCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                DAWN_TRY(ReadContentIntoTexture(*this, contentReadHead, mDevice, data));
                break;
            }
            case schema::RootCommand::QueueSubmit: {
                schema::RootCommandQueueSubmitCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));

                std::vector<wgpu::CommandBuffer> commandBuffers;
                std::transform(data.commandBuffers.begin(), data.commandBuffers.end(),
                               std::back_inserter(commandBuffers), [&](const auto id) {
                                   return GetObjectById<wgpu::CommandBuffer>(id);
                               });

                mDevice.GetQueue().Submit(commandBuffers.size(), commandBuffers.data());
                break;
            }
            case schema::RootCommand::UnmapBuffer: {
                schema::RootCommandUnmapBufferCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                wgpu::Buffer buffer = GetObjectById<wgpu::Buffer>(data.bufferId);
                DAWN_TRY(MapContentIntoBuffer(contentReadHead, mDevice, buffer, data.bufferOffset,
                                              data.size));
                break;
            }
            case schema::RootCommand::SetLabel: {
                schema::RootCommandSetLabelCmdData data;
                DAWN_TRY(Deserialize(readHead, &data));
                DAWN_TRY(SetLabel(data.id, data.type, data.label));
                break;
            }
            default: {
                return DAWN_INTERNAL_ERROR("unimplemented root command");
            }
        }
    }

    return {};
}

}  // namespace dawn::replay
