/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/dawn/DawnCommandBuffer.h"

#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/SkLog.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/UniformManager.h"
#include "src/gpu/graphite/compute/DispatchGroup.h"
#include "src/gpu/graphite/dawn/DawnBuffer.h"
#include "src/gpu/graphite/dawn/DawnCaps.h"
#include "src/gpu/graphite/dawn/DawnComputePipeline.h"
#include "src/gpu/graphite/dawn/DawnGraphicsPipeline.h"
#include "src/gpu/graphite/dawn/DawnGraphiteUtils.h"
#include "src/gpu/graphite/dawn/DawnQueueManager.h"
#include "src/gpu/graphite/dawn/DawnSampler.h"
#include "src/gpu/graphite/dawn/DawnSharedContext.h"
#include "src/gpu/graphite/dawn/DawnTexture.h"

#if defined(__EMSCRIPTEN__)
#include <emscripten/version.h>

namespace wgpu {
using TexelCopyBufferInfo = ImageCopyBuffer;
using TexelCopyTextureInfo = ImageCopyTexture;
}  // namespace wgpu
#endif

namespace skgpu::graphite {

// On emsdk before 3.1.48 the API for RenderPass and ComputePass timestamps was different
// and does not map to current webgpu. We check this in DawnCaps but we also must avoid
// naming the types from the new API because they aren't defined.
#if defined(__EMSCRIPTEN__)                                                                  \
        && ((__EMSCRIPTEN_major__ < 3)                                                       \
         || (__EMSCRIPTEN_major__ == 3 && __EMSCRIPTEN_minor__ < 1)                          \
         || (__EMSCRIPTEN_major__ == 3 && __EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ < 48))
    #define WGPU_TIMESTAMP_WRITES_DEFINED 0
#else
    #define WGPU_TIMESTAMP_WRITES_DEFINED 1
#endif

// DawnCommandBuffer
// ----------------------------------------------------------------------------
std::unique_ptr<DawnCommandBuffer> DawnCommandBuffer::Make(const DawnSharedContext* sharedContext,
                                                           DawnResourceProvider* resourceProvider) {
    std::unique_ptr<DawnCommandBuffer> cmdBuffer(
            new DawnCommandBuffer(sharedContext, resourceProvider));
    if (!cmdBuffer->setNewCommandBufferResources()) {
        return {};
    }
    return cmdBuffer;
}

DawnCommandBuffer::DawnCommandBuffer(const DawnSharedContext* sharedContext,
                                     DawnResourceProvider* resourceProvider)
        : CommandBuffer(Protected::kNo)  // Dawn doesn't support protected memory
        , fSharedContext(sharedContext)
        , fResourceProvider(resourceProvider) {}

DawnCommandBuffer::~DawnCommandBuffer() {}

bool DawnCommandBuffer::startStatsQuery(GpuStatsFlags) {
    if (fHasStatsQuery) {
        SKIA_LOG_W(
                "startTimerQuery called more than once for the same command "
                "buffer. Currently, stats queries are only supported when "
                "each recording gets its own submission.");
        return false;
    }
    wgpu::QuerySet querySet = std::move(fTimestampQuerySet);

    auto buffer = fResourceProvider->findOrCreateDawnBuffer(2 * sizeof(uint64_t),
                                                            BufferType::kQuery,
                                                            AccessPattern::kHostVisible,
                                                            "TimerQuery");
    if (!buffer) {
        SKIA_LOG_W("Failed to create buffer for resolving results, timer query will "
                    "not be reported.");
        return false;
    }
    sk_sp<DawnBuffer> xferBuffer;
    if (!fSharedContext->caps()->drawBufferCanBeMapped()) {
        xferBuffer = fResourceProvider->findOrCreateDawnBuffer(2 * sizeof(uint64_t),
                                                               BufferType::kXferGpuToCpu,
                                                               AccessPattern::kHostVisible,
                                                               "TimerQueryXfer");
        if (!xferBuffer) {
            SKIA_LOG_W("Failed to create buffer for transferring timestamp results, timer "
                        "query will not be reported.");
            return false;
        }
    }
    if (!querySet) {
        wgpu::QuerySetDescriptor descriptor;
        descriptor.count = 2;
        descriptor.label = "Command Buffer Timer Query";
        descriptor.type = wgpu::QueryType::Timestamp;
        descriptor.nextInChain = nullptr;
        querySet = fSharedContext->device().CreateQuerySet(&descriptor);
        if (!querySet) {
            SKIA_LOG_W("Failed to create query set, timer query will not be reported.");
            return false;
        }
    }

    fTimestampQuerySet = std::move(querySet);
    fTimestampQueryBuffer = std::move(buffer);
    fTimestampQueryXferBuffer = std::move(xferBuffer);

    if (fSharedContext->dawnCaps()->supportsCommandBufferTimestamps()) {
        // In native Dawn we use the writeTimeStamp method on CommandBuffer to bracket
        // the whole command buffer.
        fCommandEncoder.WriteTimestamp(fTimestampQuerySet, 0);
    } else {
        // On WebGPU the best we can do is add timestamps to each render/compute pass as we record
        // them. Since we don't know a priori how many passes there will be we write a begin
        // timestamp on the first pass and an end on every pass, overwriting the second query in the
        // set.
        fWroteFirstPassTimestamps = false;
    }

    fHasStatsQuery = true;
    return true;
}

void DawnCommandBuffer::endStatsQuery(GpuStatsFlags) {
    // Only called if startTimerQuery succeeded.
    SkASSERT(fTimestampQuerySet);
    SkASSERT(fTimestampQueryBuffer);
    if (fSharedContext->dawnCaps()->supportsCommandBufferTimestamps()) {
        fCommandEncoder.WriteTimestamp(fTimestampQuerySet, 1);
    } else if (!fWroteFirstPassTimestamps) {
        // If we didn't have any passes then we can't report anything.
        fTimestampQueryBuffer = nullptr;
        fTimestampQueryXferBuffer = nullptr;
        return;
    }
    // This resolve covers both timestamp code paths (command encoder and render/compute pass).
    fCommandEncoder.ResolveQuerySet(
            fTimestampQuerySet, 0, 2, fTimestampQueryBuffer->dawnBuffer(), 0);
    if (fTimestampQueryXferBuffer) {
        SkASSERT(fTimestampQueryBuffer->size() == fTimestampQueryBuffer->size());
        fCommandEncoder.CopyBufferToBuffer(fTimestampQueryBuffer->dawnBuffer(),
                                           /*sourceOffset=*/0,
                                           fTimestampQueryXferBuffer->dawnBuffer(),
                                           /*destinationOffset=*/0,
                                           /*size=*/fTimestampQueryBuffer->size());
        fTimestampQueryBuffer.reset();
    }
    if (fSharedContext->caps()->bufferMapsAreAsync()) {
        sk_sp<Buffer> buffer =
                fTimestampQueryXferBuffer ? fTimestampQueryXferBuffer : fTimestampQueryBuffer;
        this->addBuffersToAsyncMapOnSubmit({&buffer, 1});
    }
}

std::optional<GpuStats> DawnCommandBuffer::gpuStats() {
    auto& buffer = fTimestampQueryXferBuffer ? fTimestampQueryXferBuffer : fTimestampQueryBuffer;
    if (!buffer) {
        return {};
    }
    if (fSharedContext->caps()->bufferMapsAreAsync()) {
        if (!buffer->isMapped()) {
            return {};
        }
    }
    uint64_t* results = static_cast<uint64_t*>(buffer->map());
    if (!results) {
        SKIA_LOG_W("Failed to get timer query results because buffer couldn't be mapped.");
        return {};
    }
    if (results[1] < results[0]) {
        return {};
    }
    GpuStats stats;
    stats.elapsedTime = results[1] - results[0];
    return stats;
}

wgpu::CommandBuffer DawnCommandBuffer::finishEncoding() {
    SkASSERT(fCommandEncoder);
    wgpu::CommandBuffer cmdBuffer = fCommandEncoder.Finish();

    fCommandEncoder = nullptr;
    fResourceProvider->releasePendingIntrinsicBuffers();

    return cmdBuffer;
}

void DawnCommandBuffer::onResetCommandBuffer() {
    fActiveGraphicsPipeline = nullptr;
    fActiveRenderPassEncoder = nullptr;
    fActiveComputePassEncoder = nullptr;
    fCommandEncoder = nullptr;

    for (auto& bufferSlot : fBoundUniforms) {
        bufferSlot = {};
    }
    fBoundUniformBuffersDirty = true;
    if (fTimestampQueryBuffer && fTimestampQueryBuffer->isUnmappable()) {
        fTimestampQueryBuffer->unmap();
    }
    if (fTimestampQueryXferBuffer && fTimestampQueryXferBuffer->isUnmappable()) {
        fTimestampQueryXferBuffer->unmap();
    }
    fTimestampQueryBuffer = {};
    fTimestampQueryXferBuffer = {};
    fWroteFirstPassTimestamps = false;
    fHasStatsQuery = false;
}

bool DawnCommandBuffer::setNewCommandBufferResources() {
    SkASSERT(!fCommandEncoder);
    fCommandEncoder = fSharedContext->device().CreateCommandEncoder();
    SkASSERT(fCommandEncoder);

    return true;
}

// Requests a sampler. Dynamic samplers live in the global cache, requiring no tracking, but
// immutable samplers are created on the current graphics pipeline, and may outlive it, requiring
// further tracking.
const DawnSampler* DawnCommandBuffer::getSampler(
        const DrawPassCommands::BindTexturesAndSamplers& command, int32_t index) {
    auto desc = command.fSamplers[index];
    if (desc.isImmutable()) {
        const DawnSampler* immutableSampler = fActiveGraphicsPipeline->immutableSampler(index);
        if (immutableSampler) {
            this->trackResource(sk_ref_sp<Sampler>(immutableSampler));
        }
        return immutableSampler;
    } else {
        // Use the shared Sampler held in the global cache
        return static_cast<const DawnSampler*>(
                fSharedContext->globalCache()->getDynamicSampler(desc));
    }
}

bool DawnCommandBuffer::onAddRenderPass(const RenderPassDesc& renderPassDesc,
                                        const Texture* colorTexture,
                                        const Texture* resolveTexture,
                                        const Texture* depthStencilTexture,
                                        SkIPoint resolveOffset,
                                        SkIRect viewport,
                                        const DrawPassList& drawPasses) {
    // `viewport` has already been translated by the replay translation by the base CommandBuffer
    if (!SkIRect::Intersects(viewport, fRenderTargetBounds)) SK_UNLIKELY {
            // The entire pass is offscreen
            return true;
        }


    UniformManager intrinsicValues{Layout::kStd140};
    CollectIntrinsicUniforms(fSharedContext->caps(), viewport, fDstReadBounds, &intrinsicValues);
    const auto uniformData = UniformDataBlock::Wrap(&intrinsicValues);
    const bool usePushConstant = fSharedContext->dawnCaps()
                                         ->resourceBindingRequirements()
                                         .fUsePushConstantsForIntrinsicConstants;

    // If push constant is not supported, update the intrinsic constant buffer before starting a
    // render pass.
    if (!usePushConstant && !this->updateIntrinsicUniformsAsUBO(uniformData)) SK_UNLIKELY {
        return false;
    }

    if (!this->beginRenderPass(renderPassDesc,
                               resolveOffset,
                               colorTexture,
                               resolveTexture,
                               depthStencilTexture)) SK_UNLIKELY {
        return false;
    }

    // If push constant is supported, update the intrinsic constants after starting a render pass.
    if (usePushConstant && !this->updateIntrinsicUniformsAsPushConstant(uniformData)) SK_UNLIKELY {
        return false;
    }

    this->setViewport(viewport);

    for (const auto& drawPass : drawPasses) {
        if (!this->addDrawPass(drawPass.get())) SK_UNLIKELY {
            this->endRenderPass();
            return false;
        }
    }

    return this->endRenderPass();
}

bool DawnCommandBuffer::onAddComputePass(DispatchGroupSpan groups) {
    this->beginComputePass();
    for (const auto& group : groups) {
        group->addResourceRefs(this);
        for (const auto& dispatch : group->dispatches()) {
            this->bindComputePipeline(group->getPipeline(dispatch.fPipelineIndex));
            this->bindDispatchResources(*group, dispatch);
            if (const WorkgroupSize* globalSize =
                        std::get_if<WorkgroupSize>(&dispatch.fGlobalSizeOrIndirect)) {
                this->dispatchWorkgroups(*globalSize);
            } else {
                SkASSERT(std::holds_alternative<BindBufferInfo>(dispatch.fGlobalSizeOrIndirect));
                const BindBufferInfo& indirect =
                        *std::get_if<BindBufferInfo>(&dispatch.fGlobalSizeOrIndirect);
                this->dispatchWorkgroupsIndirect(indirect.fBuffer, indirect.fOffset);
            }
        }
    }
    this->endComputePass();
    return true;
}

bool DawnCommandBuffer::beginRenderPass(const RenderPassDesc& renderPassDesc,
                                        const SkIPoint& resolveOffset,
                                        const Texture* colorTexture,
                                        const Texture* resolveTexture,
                                        const Texture* depthStencilTexture) {
    SkASSERT(!fActiveRenderPassEncoder);
    SkASSERT(!fActiveComputePassEncoder);

    constexpr static wgpu::LoadOp wgpuLoadActionMap[]{
            wgpu::LoadOp::Load,
            wgpu::LoadOp::Clear,
            wgpu::LoadOp::Clear  // Don't care
    };
    static_assert((int)LoadOp::kLoad == 0);
    static_assert((int)LoadOp::kClear == 1);
    static_assert((int)LoadOp::kDiscard == 2);
    static_assert(std::size(wgpuLoadActionMap) == kLoadOpCount);

    constexpr static wgpu::StoreOp wgpuStoreActionMap[]{wgpu::StoreOp::Store,
                                                        wgpu::StoreOp::Discard};
    static_assert((int)StoreOp::kStore == 0);
    static_assert((int)StoreOp::kDiscard == 1);
    static_assert(std::size(wgpuStoreActionMap) == kStoreOpCount);

    wgpu::RenderPassDescriptor wgpuRenderPass = {};
    wgpu::RenderPassColorAttachment wgpuColorAttachment;
    wgpu::RenderPassDepthStencilAttachment wgpuDepthStencilAttachment;

    // Set up color attachment.
#if !defined(__EMSCRIPTEN__)
    wgpu::DawnRenderPassSampleCount mssaRenderToSingleSampledDesc;
    wgpu::RenderPassDescriptorResolveRect wgpuPartialRect = {};
    wgpu::RenderPassRenderAreaRect wgpuRenderArea = {};

    if (fSharedContext->dawnCaps()->supportsRenderPassRenderArea()) {
        wgpuRenderArea.origin.x = fRenderAreaBounds.x();
        wgpuRenderArea.origin.y = fRenderAreaBounds.y();
        wgpuRenderArea.size.width = fRenderAreaBounds.width();
        wgpuRenderArea.size.height = fRenderAreaBounds.height();
        wgpuRenderPass.nextInChain = &wgpuRenderArea;
    }
#endif

#if WGPU_TIMESTAMP_WRITES_DEFINED
#if defined(__EMSCRIPTEN__)
    wgpu::RenderPassTimestampWrites wgpuTimestampWrites;
#else
    wgpu::PassTimestampWrites wgpuTimestampWrites;
#endif
    if (!fSharedContext->dawnCaps()->supportsCommandBufferTimestamps() && fTimestampQueryBuffer) {
        SkASSERT(fTimestampQuerySet);
        wgpuTimestampWrites.querySet = fTimestampQuerySet;
        if (!fWroteFirstPassTimestamps) {
            wgpuTimestampWrites.beginningOfPassWriteIndex = 0;
            fWroteFirstPassTimestamps = true;
        }
        wgpuTimestampWrites.endOfPassWriteIndex = 1;
        wgpuRenderPass.timestampWrites = &wgpuTimestampWrites;
    }
#else
    SkASSERT(!fTimestampQueryBuffer);
#endif

    // Validate attachment descs and textures
    const auto& colorInfo = renderPassDesc.fColorAttachment;
    const auto& resolveInfo = renderPassDesc.fColorResolveAttachment;
    const auto& depthStencilInfo = renderPassDesc.fDepthStencilAttachment;
    SkASSERT(colorTexture ? colorInfo.isCompatible(colorTexture->textureInfo())
                          : colorInfo.fFormat == TextureFormat::kUnsupported);
    SkASSERT(resolveTexture ? resolveInfo.isCompatible(resolveTexture->textureInfo())
                            : resolveInfo.fFormat == TextureFormat::kUnsupported);
    SkASSERT(depthStencilTexture ? depthStencilInfo.isCompatible(depthStencilTexture->textureInfo())
                                 : depthStencilInfo.fFormat == TextureFormat::kUnsupported);

    // Set up color attachment
    bool emulateLoadStoreResolveTexture = false;
    if (colorTexture) {
        wgpuRenderPass.colorAttachments = &wgpuColorAttachment;
        wgpuRenderPass.colorAttachmentCount = 1;

        const auto* dawnColorTexture = static_cast<const DawnTexture*>(colorTexture);
        SkASSERT(dawnColorTexture->renderTextureView());
        wgpuColorAttachment.view = dawnColorTexture->renderTextureView();

        const std::array<float, 4>& clearColor = renderPassDesc.fClearColor;
        wgpuColorAttachment.clearValue = {
                clearColor[0], clearColor[1], clearColor[2], clearColor[3]};
        wgpuColorAttachment.loadOp = wgpuLoadActionMap[static_cast<int>(colorInfo.fLoadOp)];
        wgpuColorAttachment.storeOp = wgpuStoreActionMap[static_cast<int>(colorInfo.fStoreOp)];

        // Set up resolve attachment
        if (resolveTexture) {
            SkASSERT(resolveInfo.fStoreOp == StoreOp::kStore);

            const auto* dawnResolveTexture = static_cast<const DawnTexture*>(resolveTexture);
            SkASSERT(dawnResolveTexture->renderTextureView());
            wgpuColorAttachment.resolveTarget = dawnResolveTexture->renderTextureView();

            // Inclusion of a resolve texture implies the client wants to finish the
            // renderpass with a resolve.
            SkASSERT(wgpuColorAttachment.storeOp == wgpu::StoreOp::Discard);
            // But it also means we might have to load the resolve texture into the MSAA color attachment

            if (fSharedContext->dawnCaps()->emulateLoadStoreResolve()) {
                emulateLoadStoreResolveTexture = true;
            } else if (resolveInfo.fLoadOp == LoadOp::kLoad) {
                std::optional<wgpu::LoadOp> resolveLoadOp =
                        fSharedContext->dawnCaps()->resolveTextureLoadOp();
                if (resolveLoadOp.has_value()) {
                    wgpuColorAttachment.loadOp = *resolveLoadOp;
                } else {
                    // No Dawn built-in support, we need to manually load the resolve texture.
                    emulateLoadStoreResolveTexture = true;
                }
            }

            if (!emulateLoadStoreResolveTexture) {
#if !defined(__EMSCRIPTEN__)
                if (fSharedContext->dawnCaps()->supportsPartialLoadResolve()) {
                    SkIRect msaaArea = fRenderAreaBounds;
                    SkAssertResult(msaaArea.intersect(SkIRect::MakeSize(
                            colorTexture->dimensions())));
                    wgpuPartialRect.colorOffsetX = msaaArea.x();
                    wgpuPartialRect.colorOffsetY = msaaArea.y();

                    SkIRect resolveArea = fRenderAreaBounds;
                    resolveArea.offset(resolveOffset);
                    SkAssertResult(resolveArea.intersect(SkIRect::MakeSize(
                            resolveTexture->dimensions())));
                    wgpuPartialRect.resolveOffsetX = resolveArea.x();
                    wgpuPartialRect.resolveOffsetY = resolveArea.y();
                    wgpuPartialRect.width = resolveArea.width();
                    wgpuPartialRect.height = resolveArea.height();

                    wgpuPartialRect.nextInChain = wgpuRenderPass.nextInChain;
                    wgpuRenderPass.nextInChain = &wgpuPartialRect;
                } else
#endif
                {
                    SkASSERT(resolveOffset.isZero());
                }
            }

            // TODO: If the color resolve texture is read-only we can use a private (vs. memoryless)
            // msaa attachment that's coupled to the framebuffer and the StoreAndMultisampleResolve
            // action instead of loading as a draw.
        } else {
            [[maybe_unused]] bool isMSAAToSingleSampled =
                    renderPassDesc.fSampleCount > SampleCount::k1 &&
                    colorTexture->sampleCount() == SampleCount::k1;
#if defined(__EMSCRIPTEN__)
            SkASSERT(!isMSAAToSingleSampled);
#else
            if (isMSAAToSingleSampled) {
                // If render pass is multi sampled but the color attachment is single sampled, we
                // need to activate multisampled render to single sampled feature for this render
                // pass.
                SkASSERT(fSharedContext->device().HasFeature(
                        wgpu::FeatureName::MSAARenderToSingleSampled));

                mssaRenderToSingleSampledDesc.nextInChain = wgpuRenderPass.nextInChain;
                wgpuRenderPass.nextInChain = &mssaRenderToSingleSampledDesc;
                mssaRenderToSingleSampledDesc.sampleCount = (uint8_t)renderPassDesc.fSampleCount;
            }
#endif
        }
    }

    // Set up stencil/depth attachment
    if (depthStencilTexture) {
        const auto* dawnDepthStencilTexture = static_cast<const DawnTexture*>(depthStencilTexture);

        SkASSERT(dawnDepthStencilTexture->renderTextureView());
        wgpuDepthStencilAttachment.view = dawnDepthStencilTexture->renderTextureView();

        if (TextureFormatHasDepth(depthStencilInfo.fFormat)) {
            wgpuDepthStencilAttachment.depthClearValue = renderPassDesc.fClearDepth;
            wgpuDepthStencilAttachment.depthLoadOp =
                    wgpuLoadActionMap[static_cast<int>(depthStencilInfo.fLoadOp)];
            wgpuDepthStencilAttachment.depthStoreOp =
                    wgpuStoreActionMap[static_cast<int>(depthStencilInfo.fStoreOp)];
        }

        if (TextureFormatHasStencil(depthStencilInfo.fFormat)) {
            wgpuDepthStencilAttachment.stencilClearValue = renderPassDesc.fClearStencil;
            wgpuDepthStencilAttachment.stencilLoadOp =
                    wgpuLoadActionMap[static_cast<int>(depthStencilInfo.fLoadOp)];
            wgpuDepthStencilAttachment.stencilStoreOp =
                    wgpuStoreActionMap[static_cast<int>(depthStencilInfo.fStoreOp)];
        }

        wgpuRenderPass.depthStencilAttachment = &wgpuDepthStencilAttachment;
    }

    if (emulateLoadStoreResolveTexture) {
        if (!this->emulateLoadMSAAFromResolveAndBeginRenderPassEncoder(
                    renderPassDesc,
                    wgpuRenderPass,
                    resolveOffset,
                    static_cast<const DawnTexture*>(colorTexture),
                    static_cast<const DawnTexture*>(resolveTexture))) {
            return false;
        }
    }
    else {
        fActiveRenderPassEncoder = fCommandEncoder.BeginRenderPass(&wgpuRenderPass);
    }

    return true;
}

bool DawnCommandBuffer::emulateLoadMSAAFromResolveAndBeginRenderPassEncoder(
        const RenderPassDesc& intendedRenderPassDesc,
        const wgpu::RenderPassDescriptor& intendedDawnRenderPassDesc,
        const SkIPoint& resolveOffset,
        const DawnTexture* msaaTexture,
        const DawnTexture* resolveTexture) {
    SkASSERT(!fActiveRenderPassEncoder);

    const bool loadResolve =
            intendedRenderPassDesc.fColorResolveAttachment.fLoadOp == LoadOp::kLoad;

    // Override the render pass to exclude the resolve texture. We will emulate the loading &
    // resolve via blit. The resovle step will be done separately after endRenderPass()
    RenderPassDesc renderPassWithoutResolveDesc = intendedRenderPassDesc;
    renderPassWithoutResolveDesc.fColorResolveAttachment = {};

    wgpu::RenderPassColorAttachment dawnColorAttachmentWithoutResolve =
            intendedDawnRenderPassDesc.colorAttachments[0];
    dawnColorAttachmentWithoutResolve.resolveTarget = nullptr;
    dawnColorAttachmentWithoutResolve.storeOp = wgpu::StoreOp::Store;

    if (loadResolve) {
        // If we intend to load the resolve texture, then override the loadOp of the MSAA attachment
        // to Load instead of Clear.
        // This path is intended to be used when the device doesn't support transient attachments.
        // Which most likely means it is a non-tiled GPU. On non-tiled GPUs, load is a no-op so it
        // should be faster than clearing the whole MSAA attachment. Note: Dawn doesn't have any
        // DontCare loadOp.
        dawnColorAttachmentWithoutResolve.loadOp = wgpu::LoadOp::Load;
    }

    wgpu::RenderPassDescriptor dawnRenderPassDescWithoutResolve = intendedDawnRenderPassDesc;
    dawnRenderPassDescWithoutResolve.colorAttachments = &dawnColorAttachmentWithoutResolve;
    dawnRenderPassDescWithoutResolve.colorAttachmentCount = 1;

    auto renderPassEncoder = fCommandEncoder.BeginRenderPass(&dawnRenderPassDescWithoutResolve);

    SkIRect msaaArea = fRenderAreaBounds;
    msaaArea.intersect(SkIRect::MakeSize(msaaTexture->dimensions()));
    SkIRect resolveArea = fRenderAreaBounds;
    resolveArea.offset(resolveOffset);
    resolveArea.intersect(SkIRect::MakeSize(resolveTexture->dimensions()));

    if (loadResolve) {
        // Blit from the resolve texture to the MSAA texture
        if (!this->doBlitWithDraw(renderPassEncoder,
                                  renderPassWithoutResolveDesc,
                                  /*srcTextureView=*/resolveTexture->renderTextureView(),
                                  /*srcSampleCount=*/SampleCount::k1,
                                  /*srcOffset=*/resolveArea.topLeft(),
                                  /*dstBounds=*/msaaArea)) {
            renderPassEncoder.End();
            return false;
        }
    }

    fActiveRenderPassEncoder = renderPassEncoder;

    fResolveStepEmulationInfo = {msaaTexture, resolveTexture, msaaArea.topLeft(), resolveArea};

    return true;
}

bool DawnCommandBuffer::doBlitWithDraw(const wgpu::RenderPassEncoder& renderEncoder,
                                       const RenderPassDesc& frontendRenderPassDescKey,
                                       const wgpu::TextureView& srcTextureView,
                                       SampleCount srcSampleCount,
                                       const SkIPoint& srcOffset,
                                       const SkIRect& dstBounds) {
    DawnResourceProvider::BlitWithDrawEncoder blit =
            fResourceProvider->findOrCreateBlitWithDrawEncoder(frontendRenderPassDescKey,
                                                               srcSampleCount);
    if (!blit) {
        SKIA_LOG_E("Unable to create pipeline to blit with draw");
        return false;
    }

    SkASSERT(renderEncoder);

    blit.EncodeBlit(fSharedContext->device(), renderEncoder, srcTextureView, srcOffset, dstBounds);

    return true;
}

bool DawnCommandBuffer::endRenderPass() {
    SkASSERT(fActiveRenderPassEncoder);
    fActiveRenderPassEncoder.End();
    fActiveRenderPassEncoder = nullptr;

    // Return early if no resolve step's emulation is needed.
    if (!fResolveStepEmulationInfo.has_value()) {
        return true;
    }

    // Creating an intermediate render pass to copy from the MSAA texture -> resolve texture.
    RenderPassDesc intermediateRenderPassDesc = {};
    intermediateRenderPassDesc.fColorAttachment = {
            TextureInfoPriv::ViewFormat(fResolveStepEmulationInfo->fResolveTexture->textureInfo()),
            LoadOp::kLoad,
            StoreOp::kStore,
            SampleCount::k1 };

    wgpu::RenderPassColorAttachment dawnIntermediateColorAttachment;
    dawnIntermediateColorAttachment.clearValue = {0.f, 0.f, 0.f, 0.f}; // ignored
    dawnIntermediateColorAttachment.loadOp = wgpu::LoadOp::Load;
    dawnIntermediateColorAttachment.storeOp = wgpu::StoreOp::Store;
    dawnIntermediateColorAttachment.view =
            fResolveStepEmulationInfo->fResolveTexture->renderTextureView();

    wgpu::RenderPassDescriptor dawnIntermediateRenderPassDesc;
    dawnIntermediateRenderPassDesc.colorAttachmentCount = 1;
    dawnIntermediateRenderPassDesc.colorAttachments = &dawnIntermediateColorAttachment;

    auto renderPassEncoder = fCommandEncoder.BeginRenderPass(&dawnIntermediateRenderPassDesc);

    bool blitSucceeded = this->doBlitWithDraw(
            renderPassEncoder,
            intermediateRenderPassDesc,
            /*srcTextureView=*/fResolveStepEmulationInfo->fMSAATexture->renderTextureView(),
            /*srcSampleCount=*/fResolveStepEmulationInfo->fMSAATexture->textureInfo().sampleCount(),
            /*srcOffset=*/fResolveStepEmulationInfo->fMSAAAOffset,
            /*dstBounds=*/fResolveStepEmulationInfo->fResolveArea);

    renderPassEncoder.End();

    fResolveStepEmulationInfo.reset();

    return blitSucceeded;
}

bool DawnCommandBuffer::addDrawPass(DrawPass* drawPass) {
    // If there is gradient data to bind, it must be done prior to draws.
    if (drawPass->floatStorageManager()->hasData()) {
        this->bindUniformBuffer(drawPass->floatStorageManager()->getBufferInfo(),
                                UniformSlot::kGradient);
    }

    if (!drawPass->addResourceRefs(fResourceProvider, this)) SK_UNLIKELY {
        return false;
    }

    for (auto [type, cmdPtr] : drawPass->commands()) {
        switch (type) {
            case DrawPassCommands::Type::kBindGraphicsPipeline: {
                auto bgp = static_cast<DrawPassCommands::BindGraphicsPipeline*>(cmdPtr);
                if (!this->bindGraphicsPipeline(drawPass->getPipeline(bgp->fPipelineIndex)))
                    SK_UNLIKELY { return false; }
                break;
            }
            case DrawPassCommands::Type::kSetBlendConstants: {
                auto sbc = static_cast<DrawPassCommands::SetBlendConstants*>(cmdPtr);
                this->setBlendConstants(sbc->fBlendConstants);
                break;
            }
            case DrawPassCommands::Type::kBindUniformBuffer: {
                auto bub = static_cast<DrawPassCommands::BindUniformBuffer*>(cmdPtr);
                this->bindUniformBuffer(bub->fInfo, bub->fSlot);
                break;
            }
            case DrawPassCommands::Type::kBindStaticDataBuffer: {
                auto bdb = static_cast<DrawPassCommands::BindStaticDataBuffer*>(cmdPtr);
                this->bindInputBuffer(bdb->fStaticData.fBuffer, bdb->fStaticData.fOffset,
                                      DawnGraphicsPipeline::kStaticDataBufferIndex);
                break;
            }
            case DrawPassCommands::Type::kBindAppendDataBuffer: {
                auto bdb = static_cast<DrawPassCommands::BindAppendDataBuffer*>(cmdPtr);
                this->bindInputBuffer(bdb->fAppendData.fBuffer, bdb->fAppendData.fOffset,
                                      DawnGraphicsPipeline::kAppendDataBufferIndex);
                break;
            }
            case DrawPassCommands::Type::kBindIndexBuffer: {
                auto bdb = static_cast<DrawPassCommands::BindIndexBuffer*>(cmdPtr);
                this->bindIndexBuffer(
                        bdb->fIndices.fBuffer, bdb->fIndices.fOffset);
                break;
            }
            case DrawPassCommands::Type::kBindIndirectBuffer: {
                auto bdb = static_cast<DrawPassCommands::BindIndirectBuffer*>(cmdPtr);
                this->bindIndirectBuffer(
                        bdb->fIndirect.fBuffer, bdb->fIndirect.fOffset);
                break;
            }
            case DrawPassCommands::Type::kBindTexturesAndSamplers: {
                auto bts = static_cast<DrawPassCommands::BindTexturesAndSamplers*>(cmdPtr);
                this->bindTextureAndSamplers(*drawPass, *bts);
                break;
            }
            case DrawPassCommands::Type::kSetScissor: {
                auto ss = static_cast<DrawPassCommands::SetScissor*>(cmdPtr);
                this->setScissor(ss->fScissor);
                break;
            }
            case DrawPassCommands::Type::kDraw: {
                auto draw = static_cast<DrawPassCommands::Draw*>(cmdPtr);
                this->draw(draw->fType, draw->fBaseVertex, draw->fVertexCount);
                break;
            }
            case DrawPassCommands::Type::kDrawIndexed: {
                auto draw = static_cast<DrawPassCommands::DrawIndexed*>(cmdPtr);
                this->drawIndexed(
                        draw->fType, draw->fBaseIndex, draw->fIndexCount, draw->fBaseVertex);
                break;
            }
            case DrawPassCommands::Type::kDrawInstanced: {
                auto draw = static_cast<DrawPassCommands::DrawInstanced*>(cmdPtr);
                this->drawInstanced(draw->fType,
                                    draw->fBaseVertex,
                                    draw->fVertexCount,
                                    draw->fBaseInstance,
                                    draw->fInstanceCount);
                break;
            }
            case DrawPassCommands::Type::kDrawIndexedInstanced: {
                auto draw = static_cast<DrawPassCommands::DrawIndexedInstanced*>(cmdPtr);
                this->drawIndexedInstanced(draw->fType,
                                           draw->fBaseIndex,
                                           draw->fIndexCount,
                                           draw->fBaseVertex,
                                           draw->fBaseInstance,
                                           draw->fInstanceCount);
                break;
            }
            case DrawPassCommands::Type::kDrawIndirect: {
                auto draw = static_cast<DrawPassCommands::DrawIndirect*>(cmdPtr);
                this->drawIndirect(draw->fType);
                break;
            }
            case DrawPassCommands::Type::kDrawIndexedIndirect: {
                auto draw = static_cast<DrawPassCommands::DrawIndexedIndirect*>(cmdPtr);
                this->drawIndexedIndirect(draw->fType);
                break;
            }
            case DrawPassCommands::Type::kAddBarrier: {
                SKIA_LOG_E("DawnCommandBuffer does not support the addition of barriers.");
                break;
            }
        }
    }

    return true;
}

bool DawnCommandBuffer::bindGraphicsPipeline(const GraphicsPipeline* graphicsPipeline) {
    SkASSERT(fActiveRenderPassEncoder);

    auto* dawnGraphicsPipeline = static_cast<const DawnGraphicsPipeline*>(graphicsPipeline);
    auto& wgpuPipeline = dawnGraphicsPipeline->dawnRenderPipeline();
    if (!wgpuPipeline) SK_UNLIKELY {
        return false;
    }
    fActiveGraphicsPipeline = dawnGraphicsPipeline;
    fActiveRenderPassEncoder.SetPipeline(wgpuPipeline);
    fBoundUniformBuffersDirty = true;

    if (fActiveGraphicsPipeline->dstReadStrategy() == DstReadStrategy::kTextureCopy &&
        fActiveGraphicsPipeline->numFragTexturesAndSamplers() == 2) {
        // The pipeline has a single paired texture+sampler and uses texture copies for dst reads.
        // This situation comes about when the program requires complex blending but otherwise
        // is not referencing any images. Since there are no other images in play, the DrawPass
        // will not have a BindTexturesAndSamplers command that we can tack the dstCopy on to.
        // Instead we need to set the texture BindGroup ASAP to just the dstCopy.
        // TODO(b/366254117): Once we standardize on a pipeline layout across all backends, the dst
        // copy texture may not go in a group with the regular textures, in which case this binding
        // can hopefully happen in a single place (e.g. here or at the start of the renderpass and
        // not also every other time the textures are changed).
        const auto* texture = static_cast<const DawnTexture*>(fDstCopy.first);
        const auto* sampler = static_cast<const DawnSampler*>(fDstCopy.second);

        wgpu::BindGroup bindGroup =
                fResourceProvider->findOrCreateSingleTextureSamplerBindGroup(sampler, texture);

        fActiveRenderPassEncoder.SetBindGroup(
                DawnGraphicsPipeline::kTextureBindGroupIndex, bindGroup);
    }

    return true;
}

void DawnCommandBuffer::bindUniformBuffer(const BindBufferInfo& info, UniformSlot slot) {
    SkASSERT(fActiveRenderPassEncoder);

    unsigned int bufferIndex;
    switch (slot) {
        case UniformSlot::kCombinedUniforms:
            bufferIndex = DawnGraphicsPipeline::kCombinedUniformIndex;
            break;
        case UniformSlot::kGradient:
            bufferIndex = DawnGraphicsPipeline::kGradientBufferIndex;
            break;
    }

    fBoundUniforms[bufferIndex] = info;
    fBoundUniformBuffersDirty = true;
}

void DawnCommandBuffer::bindInputBuffer(const Buffer* buffer, size_t offset,
                                        uint32_t bindingIndex) {
    SkASSERT(fActiveRenderPassEncoder);
    if (buffer) {
        auto dawnBuffer = static_cast<const DawnBuffer*>(buffer)->dawnBuffer();
        fActiveRenderPassEncoder.SetVertexBuffer(bindingIndex, dawnBuffer, offset);
    }
}

void DawnCommandBuffer::bindIndexBuffer(const Buffer* indexBuffer, size_t offset) {
    SkASSERT(fActiveRenderPassEncoder);
    if (indexBuffer) {
        auto dawnBuffer = static_cast<const DawnBuffer*>(indexBuffer)->dawnBuffer();
        fActiveRenderPassEncoder.SetIndexBuffer(
                dawnBuffer, wgpu::IndexFormat::Uint16, offset);
    }
}

void DawnCommandBuffer::bindIndirectBuffer(const Buffer* indirectBuffer, size_t offset) {
    if (indirectBuffer) {
        fCurrentIndirectBuffer = static_cast<const DawnBuffer*>(indirectBuffer)->dawnBuffer();
        fCurrentIndirectBufferOffset = offset;
    } else {
        fCurrentIndirectBuffer = nullptr;
        fCurrentIndirectBufferOffset = 0;
    }
}

void DawnCommandBuffer::bindTextureAndSamplers(
        const DrawPass& drawPass, const DrawPassCommands::BindTexturesAndSamplers& command) {
    SkASSERT(fActiveRenderPassEncoder);
    SkASSERT(fActiveGraphicsPipeline);

    // When there's an active graphics pipeline with a texture-copy dstread requirement, add one
    // to account for the intrinsic dstCopy texture we bind here.
    // NOTE: This is in units of pairs of textures and samplers, whereas the value reported by
    // the current pipeline is in net bindings (textures + samplers).
    int numTexturesAndSamplers = command.fNumTexSamplers;
    if (fActiveGraphicsPipeline->dstReadStrategy() == DstReadStrategy::kTextureCopy) {
        numTexturesAndSamplers++;
    }
    SkASSERT(fActiveGraphicsPipeline->numFragTexturesAndSamplers() == 2*numTexturesAndSamplers);

    // If possible, it's ideal to optimize for the common case of using a single texture with one
    // dynamic sampler. When using only one sampler, determine whether it is static or dynamic.
    bool usingSingleStaticSampler = false;
#if !defined(__EMSCRIPTEN__)
    if (command.fNumTexSamplers == 1) {
        const wgpu::YCbCrVkDescriptor& ycbcrDesc =
                TextureInfoPriv::Get<DawnTextureInfo>(
                    command.fTextures[0]->texture()->textureInfo())
                        .fYcbcrVkDescriptor;
        usingSingleStaticSampler = DawnDescriptorIsValid(ycbcrDesc);
    }
#endif

    const auto& groupLayouts = fActiveGraphicsPipeline->dawnGroupLayouts();
    wgpu::BindGroupLayout groupLayout = groupLayouts[DawnGraphicsPipeline::kTextureBindGroupIndex];

    wgpu::BindGroup bindGroup;
    // Optimize for single texture with dynamic sampling.
    if (numTexturesAndSamplers == 1 && !usingSingleStaticSampler) {
        SkASSERT(fActiveGraphicsPipeline->numFragTexturesAndSamplers() == 2);
        SkASSERT(fActiveGraphicsPipeline->dstReadStrategy() != DstReadStrategy::kTextureCopy);

        const auto* texture = static_cast<const DawnTexture*>(command.fTextures[0]->texture());
        const auto* sampler = this->getSampler(command, 0);

        bindGroup = fResourceProvider->findOrCreateSingleTextureSamplerBindGroup(sampler, texture);
    } else {
        std::vector<wgpu::BindGroupEntry> entries;

        for (int i = 0; i < command.fNumTexSamplers; ++i) {
            const auto* texture = static_cast<const DawnTexture*>(command.fTextures[i]->texture());
            const auto* sampler = this->getSampler(command, i);
            auto& wgpuTextureView = texture->sampleTextureView();
            auto& wgpuSampler = sampler->dawnSampler();

#if !defined(__EMSCRIPTEN__)
            // Assuming shader generator assigns binding slot to sampler then texture,
            // then the next sampler and texture, and so on, we need to use
            // 2 * i as base binding index of the sampler and texture.
            // TODO: https://b.corp.google.com/issues/259457090:
            // Better configurable way of assigning samplers and textures' bindings.
            const wgpu::YCbCrVkDescriptor& ycbcrDesc =
                    texture->dawnTextureInfo().fYcbcrVkDescriptor;

            // Only add a sampler as a bind group entry if it's a regular dynamic sampler. A valid
            // YCbCrVkDescriptor indicates the usage of a static sampler, which should not be
            // included here. They should already be fully specified in the bind group layout.
            if (!DawnDescriptorIsValid(ycbcrDesc)) {
#endif
                wgpu::BindGroupEntry samplerEntry;
                samplerEntry.binding = 2 * i;
                samplerEntry.sampler = wgpuSampler;
                entries.push_back(samplerEntry);
#if !defined(__EMSCRIPTEN__)
            }
#endif
            wgpu::BindGroupEntry textureEntry;
            textureEntry.binding = 2 * i + 1;
            textureEntry.textureView = wgpuTextureView;
            entries.push_back(textureEntry);
        }

        if (fActiveGraphicsPipeline->dstReadStrategy() == DstReadStrategy::kTextureCopy) {
            // Append the dstCopy sampler and texture as the very last two bind group entries
            wgpu::BindGroupEntry samplerEntry;
            samplerEntry.binding = 2*numTexturesAndSamplers - 2;
            samplerEntry.sampler = static_cast<const DawnSampler*>(fDstCopy.second)->dawnSampler();
            entries.push_back(samplerEntry);

            wgpu::BindGroupEntry textureEntry;
            textureEntry.binding = 2*numTexturesAndSamplers - 1;
            textureEntry.textureView =
                    static_cast<const DawnTexture*>(fDstCopy.first)->sampleTextureView();
            entries.push_back(textureEntry);
        }

        bindGroup = fResourceProvider->createBindGroup(entries, groupLayout);
    }

    fActiveRenderPassEncoder.SetBindGroup(DawnGraphicsPipeline::kTextureBindGroupIndex, bindGroup);
}

void DawnCommandBuffer::syncUniformBuffers() {
    if (!fBoundUniformBuffersDirty) {
        return;
    }
    fBoundUniformBuffersDirty = false;

    bool usePushConstants = fSharedContext->dawnCaps()->
            resourceBindingRequirements().fUsePushConstantsForIntrinsicConstants;

    // We expect to have up to 3 uniforms in this bind group.
    static constexpr int kMaxUniformsInGroup = 3;
    // Until/unless uniform bind group structure gets reorganized, this should be equivalent to the
    // size of our bound uniform array.
    SkASSERT(kMaxUniformsInGroup == fBoundUniforms.size());

    wgpu::BindGroup bindGroup;
    std::array<uint32_t, kMaxUniformsInGroup> dynamicOffsets {0};
    // Check if we can use an optimized route for single-uniform buffer bind groups:
    if (usePushConstants &&
        !fActiveGraphicsPipeline->hasGradientBuffer() &&
        fActiveGraphicsPipeline->hasCombinedUniforms()) {
        const BindBufferInfo& bufferInfo =
                fBoundUniforms[DawnGraphicsPipeline::kCombinedUniformIndex];
        bindGroup = fResourceProvider->findOrCreateSingleUniformBindGroup(bufferInfo);
        dynamicOffsets[DawnGraphicsPipeline::kCombinedUniformIndex] = bufferInfo.fOffset;
    } else {
        std::array<bool, kMaxUniformsInGroup> enabled = {
                !usePushConstants,                              // intrinsic uniforms
                fActiveGraphicsPipeline->hasCombinedUniforms(), // paint AND renderstep uniforms!
                fActiveGraphicsPipeline->hasGradientBuffer(),   // gradient SSBO
        };
        constexpr uint32_t kBindingIndices[] = {
            DawnGraphicsPipeline::kIntrinsicUniformBufferIndex,
            DawnGraphicsPipeline::kCombinedUniformIndex,
            DawnGraphicsPipeline::kGradientBufferIndex,
        };

        std::array<wgpu::BindGroupEntry, kMaxUniformsInGroup> bindGroupEntries {};
        for (int i = 0; i < kMaxUniformsInGroup; ++i) {
            bindGroupEntries[i].binding = kBindingIndices[i];
            if (enabled[i] && fBoundUniforms[i]) {
                bindGroupEntries[i].size = fBoundUniforms[i].fSize;
                bindGroupEntries[i].buffer =
                        static_cast<const DawnBuffer*>(fBoundUniforms[i].fBuffer)->dawnBuffer();
                dynamicOffsets[i] = fBoundUniforms[i].fOffset;
            } else {
                // Unused or null binding
                bindGroupEntries[i].buffer = fResourceProvider->getOrCreateNullBuffer();
            }
        }

        const auto& groupLayouts = fActiveGraphicsPipeline->dawnGroupLayouts();
        bindGroup = fResourceProvider->createBindGroup(
                bindGroupEntries,
                groupLayouts[DawnGraphicsPipeline::kUniformBufferBindGroupIndex]);
    }

    fActiveRenderPassEncoder.SetBindGroup(DawnGraphicsPipeline::kUniformBufferBindGroupIndex,
                                          bindGroup,
                                          dynamicOffsets.size(),
                                          dynamicOffsets.data());
}

void DawnCommandBuffer::setScissor(const Scissor& scissor) {
    SkASSERT(fActiveRenderPassEncoder);
    SkIRect rect = scissor.getRect(fReplayTranslation, fRenderAreaBounds);
    fActiveRenderPassEncoder.SetScissorRect(rect.x(), rect.y(), rect.width(), rect.height());
}

bool DawnCommandBuffer::updateIntrinsicUniformsAsUBO(UniformDataBlock uniformData) {
    BindBufferInfo binding =
            fResourceProvider->findOrCreateIntrinsicBindBufferInfo(this, uniformData);

    if (!binding) {
        return false;
    } else if (binding == fBoundUniforms[DawnGraphicsPipeline::kIntrinsicUniformBufferIndex]) {
        return true; // no binding change needed
    }

    fBoundUniforms[DawnGraphicsPipeline::kIntrinsicUniformBufferIndex] = binding;
    fBoundUniformBuffersDirty = true;
    return true;
}

bool DawnCommandBuffer::updateIntrinsicUniformsAsPushConstant(UniformDataBlock uniformData) {
#if !defined(__EMSCRIPTEN__)
    SkASSERT(fActiveRenderPassEncoder);
    SkASSERT(uniformData.size() <= DawnGraphicsPipeline::kIntrinsicUniformSize);
    fActiveRenderPassEncoder.SetImmediates(0, uniformData.data(), uniformData.size());
    return true;
#else
    SkASSERT(false); // No push constant support in WASM yet
    return false;
#endif
}

void DawnCommandBuffer::setViewport(SkIRect viewport) {
    SkASSERT(fActiveRenderPassEncoder);
    fActiveRenderPassEncoder.SetViewport(
            viewport.x(), viewport.y(), viewport.width(), viewport.height(), 0, 1);
}

void DawnCommandBuffer::setBlendConstants(std::array<float, 4> blendConstants) {
    SkASSERT(fActiveRenderPassEncoder);
    wgpu::Color blendConst = {
            blendConstants[0], blendConstants[1], blendConstants[2], blendConstants[3]};
    fActiveRenderPassEncoder.SetBlendConstant(&blendConst);
}

void DawnCommandBuffer::draw(PrimitiveType type,
                             unsigned int baseVertex,
                             unsigned int vertexCount) {
    SkASSERT(fActiveRenderPassEncoder);
    SkASSERT(fActiveGraphicsPipeline->primitiveType() == type);

    this->syncUniformBuffers();

    fActiveRenderPassEncoder.Draw(vertexCount, /*instanceCount=*/1, baseVertex);
}

void DawnCommandBuffer::drawIndexed(PrimitiveType type,
                                    unsigned int baseIndex,
                                    unsigned int indexCount,
                                    unsigned int baseVertex) {
    SkASSERT(fActiveRenderPassEncoder);
    SkASSERT(fActiveGraphicsPipeline->primitiveType() == type);

    this->syncUniformBuffers();

    fActiveRenderPassEncoder.DrawIndexed(indexCount, /*instanceCount=*/1, baseIndex, baseVertex);
}

void DawnCommandBuffer::drawInstanced(PrimitiveType type,
                                      unsigned int baseVertex,
                                      unsigned int vertexCount,
                                      unsigned int baseInstance,
                                      unsigned int instanceCount) {
    SkASSERT(fActiveRenderPassEncoder);
    SkASSERT(fActiveGraphicsPipeline->primitiveType() == type);

    this->syncUniformBuffers();

    fActiveRenderPassEncoder.Draw(vertexCount, instanceCount, baseVertex, baseInstance);
}

void DawnCommandBuffer::drawIndexedInstanced(PrimitiveType type,
                                             unsigned int baseIndex,
                                             unsigned int indexCount,
                                             unsigned int baseVertex,
                                             unsigned int baseInstance,
                                             unsigned int instanceCount) {
    SkASSERT(fActiveRenderPassEncoder);
    SkASSERT(fActiveGraphicsPipeline->primitiveType() == type);

    this->syncUniformBuffers();

    fActiveRenderPassEncoder.DrawIndexed(
            indexCount, instanceCount, baseIndex, baseVertex, baseInstance);
}

void DawnCommandBuffer::drawIndirect(PrimitiveType type) {
    SkASSERT(fActiveRenderPassEncoder);
    SkASSERT(fActiveGraphicsPipeline->primitiveType() == type);
    SkASSERT(fCurrentIndirectBuffer);

    this->syncUniformBuffers();

    fActiveRenderPassEncoder.DrawIndirect(fCurrentIndirectBuffer, fCurrentIndirectBufferOffset);
}

void DawnCommandBuffer::drawIndexedIndirect(PrimitiveType type) {
    SkASSERT(fActiveRenderPassEncoder);
    SkASSERT(fActiveGraphicsPipeline->primitiveType() == type);
    SkASSERT(fCurrentIndirectBuffer);

    this->syncUniformBuffers();

    fActiveRenderPassEncoder.DrawIndexedIndirect(fCurrentIndirectBuffer,
                                                 fCurrentIndirectBufferOffset);
}

void DawnCommandBuffer::beginComputePass() {
    SkASSERT(!fActiveRenderPassEncoder);
    SkASSERT(!fActiveComputePassEncoder);
    wgpu::ComputePassDescriptor wgpuComputePassDescriptor = {};
#if WGPU_TIMESTAMP_WRITES_DEFINED
#if defined(__EMSCRIPTEN__)
    wgpu::ComputePassTimestampWrites wgpuTimestampWrites;
#else
    wgpu::PassTimestampWrites wgpuTimestampWrites;
#endif
    if (!fSharedContext->dawnCaps()->supportsCommandBufferTimestamps() && fTimestampQueryBuffer) {
        SkASSERT(fTimestampQuerySet);
        wgpuTimestampWrites.querySet = fTimestampQuerySet;
        if (!fWroteFirstPassTimestamps) {
            wgpuTimestampWrites.beginningOfPassWriteIndex = 0;
            fWroteFirstPassTimestamps = true;
        }
        wgpuTimestampWrites.endOfPassWriteIndex = 1;
        wgpuComputePassDescriptor.timestampWrites = &wgpuTimestampWrites;
    }
#else
    SkASSERT(!fTimestampQueryBuffer);
#endif
    fActiveComputePassEncoder = fCommandEncoder.BeginComputePass(&wgpuComputePassDescriptor);
}

void DawnCommandBuffer::bindComputePipeline(const ComputePipeline* computePipeline) {
    SkASSERT(fActiveComputePassEncoder);

    fActiveComputePipeline = static_cast<const DawnComputePipeline*>(computePipeline);
    fActiveComputePassEncoder.SetPipeline(fActiveComputePipeline->dawnComputePipeline());
}

void DawnCommandBuffer::bindDispatchResources(const DispatchGroup& group,
                                              const DispatchGroup::Dispatch& dispatch) {
    SkASSERT(fActiveComputePassEncoder);
    SkASSERT(fActiveComputePipeline);

    // Bind all pipeline resources to a single new bind group at index 0.
    // NOTE: Caching the bind groups here might be beneficial based on the layout and the bound
    // resources (though it's questionable how often a bind group will end up getting reused since
    // the bound objects change often).
    skia_private::TArray<wgpu::BindGroupEntry> entries;
    entries.reserve(dispatch.fBindings.size());

    for (const ResourceBinding& binding : dispatch.fBindings) {
        wgpu::BindGroupEntry& entry = entries.push_back();
        entry.binding = binding.fIndex;
        if (const BindBufferInfo* buffer = std::get_if<BindBufferInfo>(&binding.fResource)) {
            entry.buffer = static_cast<const DawnBuffer*>(buffer->fBuffer)->dawnBuffer();
            entry.offset = buffer->fOffset;
            entry.size = buffer->fSize;
        } else if (const TextureIndex* texIdx = std::get_if<TextureIndex>(&binding.fResource)) {
            const DawnTexture* texture =
                    static_cast<const DawnTexture*>(group.getTexture(texIdx->fValue));
            SkASSERT(texture);
            entry.textureView = texture->sampleTextureView();
        } else if (const SamplerIndex* samplerIdx = std::get_if<SamplerIndex>(&binding.fResource)) {
            const DawnSampler* sampler =
                    static_cast<const DawnSampler*>(group.getSampler(samplerIdx->fValue));
            entry.sampler = sampler->dawnSampler();
        } else {
            SK_ABORT("unsupported dispatch resource type");
        }
    }

    wgpu::BindGroupDescriptor desc;
    desc.layout = fActiveComputePipeline->dawnGroupLayout();
    desc.entryCount = entries.size();
    desc.entries = entries.data();

    auto bindGroup = fSharedContext->device().CreateBindGroup(&desc);
    fActiveComputePassEncoder.SetBindGroup(0, bindGroup);
}

void DawnCommandBuffer::dispatchWorkgroups(const WorkgroupSize& globalSize) {
    SkASSERT(fActiveComputePassEncoder);
    SkASSERT(fActiveComputePipeline);

    fActiveComputePassEncoder.DispatchWorkgroups(
            globalSize.fWidth, globalSize.fHeight, globalSize.fDepth);
}

void DawnCommandBuffer::dispatchWorkgroupsIndirect(const Buffer* indirectBuffer,
                                                   size_t indirectBufferOffset) {
    SkASSERT(fActiveComputePassEncoder);
    SkASSERT(fActiveComputePipeline);

    auto& wgpuIndirectBuffer = static_cast<const DawnBuffer*>(indirectBuffer)->dawnBuffer();
    fActiveComputePassEncoder.DispatchWorkgroupsIndirect(wgpuIndirectBuffer, indirectBufferOffset);
}

void DawnCommandBuffer::endComputePass() {
    SkASSERT(fActiveComputePassEncoder);
    fActiveComputePassEncoder.End();
    fActiveComputePassEncoder = nullptr;
}

bool DawnCommandBuffer::onCopyBufferToBuffer(const Buffer* srcBuffer,
                                             size_t srcOffset,
                                             const Buffer* dstBuffer,
                                             size_t dstOffset,
                                             size_t size) {
    SkASSERT(!fActiveRenderPassEncoder);
    SkASSERT(!fActiveComputePassEncoder);

    auto& wgpuBufferSrc = static_cast<const DawnBuffer*>(srcBuffer)->dawnBuffer();
    auto& wgpuBufferDst = static_cast<const DawnBuffer*>(dstBuffer)->dawnBuffer();

    fCommandEncoder.CopyBufferToBuffer(wgpuBufferSrc, srcOffset, wgpuBufferDst, dstOffset, size);
    return true;
}

bool DawnCommandBuffer::onCopyTextureToBuffer(const Texture* texture,
                                              SkIRect srcRect,
                                              const Buffer* buffer,
                                              size_t bufferOffset,
                                              size_t bufferRowBytes) {
    SkASSERT(!fActiveRenderPassEncoder);
    SkASSERT(!fActiveComputePassEncoder);

    const auto* wgpuTexture = static_cast<const DawnTexture*>(texture);
    auto& wgpuBuffer = static_cast<const DawnBuffer*>(buffer)->dawnBuffer();

    wgpu::TexelCopyTextureInfo src;
    src.texture = wgpuTexture->dawnTexture();
    src.origin.x = srcRect.x();
    src.origin.y = srcRect.y();
    src.aspect = wgpuTexture->dawnTextureInfo().fAspect;

    wgpu::TexelCopyBufferInfo dst;
    dst.buffer = wgpuBuffer;
    dst.layout.offset = bufferOffset;
    dst.layout.bytesPerRow = bufferRowBytes;

    wgpu::Extent3D copySize = {
            static_cast<uint32_t>(srcRect.width()), static_cast<uint32_t>(srcRect.height()), 1};
    fCommandEncoder.CopyTextureToBuffer(&src, &dst, &copySize);

    return true;
}

bool DawnCommandBuffer::onCopyBufferToTexture(const Buffer* buffer,
                                              const Texture* texture,
                                              const BufferTextureCopyData* copyData,
                                              int count) {
    SkASSERT(!fActiveRenderPassEncoder);
    SkASSERT(!fActiveComputePassEncoder);

    auto& wgpuTexture = static_cast<const DawnTexture*>(texture)->dawnTexture();
    auto& wgpuBuffer = static_cast<const DawnBuffer*>(buffer)->dawnBuffer();

    wgpu::TexelCopyBufferInfo src;
    src.buffer = wgpuBuffer;

    wgpu::TexelCopyTextureInfo dst;
    dst.texture = wgpuTexture;

    for (int i = 0; i < count; ++i) {
        src.layout.offset = copyData[i].fBufferOffset;
        src.layout.bytesPerRow = copyData[i].fBufferRowBytes;

        dst.origin.x = copyData[i].fRect.x();
        dst.origin.y = copyData[i].fRect.y();
        dst.mipLevel = copyData[i].fMipLevel;

        wgpu::Extent3D copySize = {static_cast<uint32_t>(copyData[i].fRect.width()),
                                   static_cast<uint32_t>(copyData[i].fRect.height()),
                                   1};
        fCommandEncoder.CopyBufferToTexture(&src, &dst, &copySize);
    }

    return true;
}

bool DawnCommandBuffer::onCopyTextureToTexture(const Texture* src,
                                               SkIRect srcRect,
                                               const Texture* dst,
                                               SkIPoint dstPoint,
                                               int mipLevel) {
    SkASSERT(!fActiveRenderPassEncoder);
    SkASSERT(!fActiveComputePassEncoder);

    auto& wgpuTextureSrc = static_cast<const DawnTexture*>(src)->dawnTexture();
    auto& wgpuTextureDst = static_cast<const DawnTexture*>(dst)->dawnTexture();

    wgpu::TexelCopyTextureInfo srcArgs;
    srcArgs.texture = wgpuTextureSrc;
    srcArgs.origin.x = srcRect.fLeft;
    srcArgs.origin.y = srcRect.fTop;

    wgpu::TexelCopyTextureInfo dstArgs;
    dstArgs.texture = wgpuTextureDst;
    dstArgs.origin.x = dstPoint.fX;
    dstArgs.origin.y = dstPoint.fY;
    dstArgs.mipLevel = mipLevel;

    wgpu::Extent3D copySize = {
            static_cast<uint32_t>(srcRect.width()), static_cast<uint32_t>(srcRect.height()), 1};

    fCommandEncoder.CopyTextureToTexture(&srcArgs, &dstArgs, &copySize);

    return true;
}

bool DawnCommandBuffer::onSynchronizeBufferToCpu(const Buffer* buffer, bool* outDidResultInWork) {
    return true;
}

bool DawnCommandBuffer::onClearBuffer(const Buffer* buffer, size_t offset, size_t size) {
    SkASSERT(!fActiveRenderPassEncoder);
    SkASSERT(!fActiveComputePassEncoder);

    auto& wgpuBuffer = static_cast<const DawnBuffer*>(buffer)->dawnBuffer();
    fCommandEncoder.ClearBuffer(wgpuBuffer, offset, size);

    return true;
}

}  // namespace skgpu::graphite
