/*
 * 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/DawnResourceProvider.h"

#include "include/core/SkString.h"
#include "include/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/gpu/graphite/dawn/DawnGraphiteTypes.h"
#include "include/private/SingleOwner.h"
#include "include/private/SkAlign.h"
#include "src/gpu/graphite/ComputePipeline.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/StorageContext.h"
#include "src/gpu/graphite/dawn/DawnBuffer.h"
#include "src/gpu/graphite/dawn/DawnCommandBuffer.h"
#include "src/gpu/graphite/dawn/DawnComputePipeline.h"
#include "src/gpu/graphite/dawn/DawnErrorChecker.h"
#include "src/gpu/graphite/dawn/DawnGraphicsPipeline.h"
#include "src/gpu/graphite/dawn/DawnGraphiteUtils.h"
#include "src/gpu/graphite/dawn/DawnSampler.h"
#include "src/gpu/graphite/dawn/DawnSharedContext.h"
#include "src/gpu/graphite/dawn/DawnTexture.h"
#include "src/sksl/SkSLCompiler.h"

namespace skgpu::graphite {

namespace {

constexpr uint32_t kBufferBindingSizeAlignment = 16;

wgpu::ShaderModule create_shader_module(const wgpu::Device& device, const char* source) {
#if defined(__EMSCRIPTEN__)
    wgpu::ShaderModuleWGSLDescriptor wgslDesc;
#else
    wgpu::ShaderSourceWGSL wgslDesc;
#endif
    wgslDesc.code = source;
    wgpu::ShaderModuleDescriptor descriptor;
    descriptor.nextInChain = &wgslDesc;
    return device.CreateShaderModule(&descriptor);
}

wgpu::RenderPipeline create_blit_render_pipeline(const DawnSharedContext* sharedContext,
                                                 const char* label,
                                                 wgpu::ShaderModule shaderModule,
                                                 const char* vsEntryPoint,
                                                 const char* fsEntryPoint,
                                                 wgpu::TextureFormat renderPassColorFormat,
                                                 wgpu::TextureFormat renderPassDepthStencilFormat,
                                                 SampleCount sampleCount) {
    wgpu::RenderPipelineDescriptor descriptor;
    descriptor.label = label;
    descriptor.layout = nullptr;

    wgpu::ColorTargetState colorTarget;
    colorTarget.format = renderPassColorFormat;
    colorTarget.blend = nullptr;
    colorTarget.writeMask = wgpu::ColorWriteMask::All;

    wgpu::DepthStencilState depthStencil;
    if (renderPassDepthStencilFormat != wgpu::TextureFormat::Undefined) {
        depthStencil.format = renderPassDepthStencilFormat;
        depthStencil.depthWriteEnabled = false;
        depthStencil.depthCompare = wgpu::CompareFunction::Always;

        descriptor.depthStencil = &depthStencil;
    }

    wgpu::FragmentState fragment;
    fragment.module = shaderModule;
    fragment.entryPoint = fsEntryPoint;
    fragment.constantCount = 0;
    fragment.constants = nullptr;
    fragment.targetCount = 1;
    fragment.targets = &colorTarget;
    descriptor.fragment = &fragment;

    descriptor.vertex.module = shaderModule;
    descriptor.vertex.entryPoint = vsEntryPoint;
    descriptor.vertex.constantCount = 0;
    descriptor.vertex.constants = nullptr;
    descriptor.vertex.bufferCount = 0;
    descriptor.vertex.buffers = nullptr;

    descriptor.primitive.frontFace = wgpu::FrontFace::CCW;
    descriptor.primitive.cullMode = wgpu::CullMode::None;
    descriptor.primitive.topology = wgpu::PrimitiveTopology::TriangleStrip;
    descriptor.primitive.stripIndexFormat = wgpu::IndexFormat::Undefined;

    descriptor.multisample.count = (uint8_t) sampleCount;
    descriptor.multisample.mask = 0xFFFFFFFF;
    descriptor.multisample.alphaToCoverageEnabled = false;

    std::optional<DawnErrorChecker> errorChecker;
    if (sharedContext->dawnCaps()->allowScopedErrorChecks()) {
        errorChecker.emplace(sharedContext);
    }
    auto pipeline = sharedContext->device().CreateRenderPipeline(&descriptor);
    if (errorChecker.has_value() && errorChecker->popErrorScopes() != DawnErrorType::kNoError) {
        return nullptr;
    }

    return pipeline;
}
} // namespace

// Wraps a Dawn buffer, and tracks the intrinsic blocks residing in this buffer.
class DawnResourceProvider::IntrinsicBuffer final {
public:
    static constexpr int kNumSlots = 8;

    IntrinsicBuffer(sk_sp<DawnBuffer> dawnBuffer) : fDawnBuffer(std::move(dawnBuffer)) {}
    ~IntrinsicBuffer() = default;

    sk_sp<DawnBuffer> buffer() const { return fDawnBuffer; }

    // Track that 'intrinsicValues' is stored in the buffer at the 'offset'.
    void trackIntrinsic(UniformDataBlock intrinsicValues, uint32_t offset) {
        fCachedIntrinsicValues.set(UniformDataBlock::Make(intrinsicValues, &fUniformData), offset);
    }

    // Find the offset of 'intrinsicValues' in the buffer. If not found, return nullptr.
    uint32_t* findIntrinsic(UniformDataBlock intrinsicValues) const {
        return fCachedIntrinsicValues.find(intrinsicValues);
    }

    int slotsUsed() const { return fCachedIntrinsicValues.count(); }

    void updateAccessTime() {
        fLastAccess = skgpu::StdSteadyClock::now();
    }
    skgpu::StdSteadyClock::time_point lastAccessTime() const {
        return fLastAccess;
    }

private:
    skia_private::THashMap<UniformDataBlock, uint32_t, UniformDataBlock::Hash>
        fCachedIntrinsicValues;
    SkArenaAlloc fUniformData{0};

    sk_sp<DawnBuffer> fDawnBuffer;
    skgpu::StdSteadyClock::time_point fLastAccess;

    SK_DECLARE_INTERNAL_LLIST_INTERFACE(IntrinsicBuffer);
};

// DawnResourceProvider::IntrinsicConstantsManager
// ----------------------------------------------------------------------------

/**
 * Since Dawn does not currently provide push constants, this helper class manages rotating through
 * buffers and writing each new occurrence of a set of intrinsic uniforms into the current buffer.
 */
class DawnResourceProvider::IntrinsicConstantsManager {
public:
    explicit IntrinsicConstantsManager(DawnResourceProvider* resourceProvider)
            : fResourceProvider(resourceProvider) {}

    ~IntrinsicConstantsManager() {
        auto alwaysTrue = [](IntrinsicBuffer* buffer) { return true; };
        this->purgeBuffersUntilDoneOrFalse(alwaysTrue);
        this->releasePendingIntrinsicBuffers();

        SkASSERT(fIntrinsicBuffersLRU.isEmpty());
    }

    // Find or create a bind buffer info for the given intrinsic values used in the given command
    // buffer.
    BindBufferInfo add(DawnCommandBuffer* cb, UniformDataBlock intrinsicValues);

    void purgeResourcesNotUsedSince(StdSteadyClock::time_point purgeTime,
                                    std::optional<StdSteadyClock::time_point> quitPurgingTime) {
        auto bufferShouldBePurged = [&](IntrinsicBuffer* buffer) {
            // We always keep the current buffer as it is likely to be used again soon. If we
            // surpass quitPurgingTime, further buffers should not be purged.
            return ( !quitPurgingTime.has_value() ||
                     skgpu::StdSteadyClock::now() < quitPurgingTime.value()) &&
                   (buffer != fCurrentBuffer && buffer->lastAccessTime() < purgeTime);
        };
        this->purgeBuffersUntilDoneOrFalse(bufferShouldBePurged);
    }

    void releasePendingIntrinsicBuffers() {
        using Iter = SkTInternalLList<IntrinsicBuffer>::Iter;
        Iter iter;
        auto* curr = iter.init(fPendingIntrinsicBuffers, Iter::kHead_IterStart);
        while (curr != nullptr) {
            auto* next = iter.next();

            fPendingIntrinsicBuffers.remove(curr);
            delete curr;

            curr = next;
        }
    }

    void freeGpuResources() {
        this->purgeResourcesNotUsedSince(skgpu::StdSteadyClock::now(),
                                         /*quitPurgingTime=*/std::nullopt);
    }

private:
    // The max number of intrinsic buffers to keep around in the cache.
    static constexpr uint32_t kMaxNumBuffers = 16;

    // Traverse the intrinsic buffers, purging all the purgeable LRU buffers until either all of
    // them are purged OR until `pred` returns false.
    template<typename T> void purgeBuffersUntilDoneOrFalse(T pred);

    DawnResourceProvider* const fResourceProvider;
    // The current buffer being filled up, as well as the how much of it has been written to.
    IntrinsicBuffer* fCurrentBuffer = nullptr;

    // All cached intrinsic buffers, in LRU order.
    SkTInternalLList<IntrinsicBuffer> fIntrinsicBuffersLRU;
    // The number of intrinsic buffers currently in the cache.
    uint32_t fNumBuffers = 0;

    // Linked list of instrinsic buffers which have been bumped out of the LRU. Is cleared when the
    // command buffer is finished.
    SkTInternalLList<IntrinsicBuffer> fPendingIntrinsicBuffers;
};

// Find or create a bind buffer info for the given intrinsic values used in the given command
// buffer.
BindBufferInfo DawnResourceProvider::IntrinsicConstantsManager::add(
        DawnCommandBuffer* cb, UniformDataBlock intrinsicValues) {
    using Iter = SkTInternalLList<IntrinsicBuffer>::Iter;
    Iter iter;
    auto* curr = iter.init(fIntrinsicBuffersLRU, Iter::kHead_IterStart);
    uint32_t* offset = nullptr;
    // Find the buffer that contains the given intrinsic values.
    while (curr != nullptr) {
        offset = curr->findIntrinsic(intrinsicValues);
        if (offset != nullptr) {
            break;
        }
        curr = iter.next();
    }
    // If we found the buffer, we can return the bind buffer info directly.
    if (curr != nullptr && offset != nullptr) {
        // Move the buffer to the head of the LRU list.
        fIntrinsicBuffersLRU.remove(curr);
        fIntrinsicBuffersLRU.addToHead(curr);
        // Track the dawn buffer's usage by the command buffer.
        cb->trackResource(curr->buffer());
        curr->updateAccessTime();
        return {curr->buffer().get(), *offset, SkTo<uint32_t>(intrinsicValues.size())};
    }

    // TODO: https://b.corp.google.com/issues/259267703
    // Make updating intrinsic constants faster. Metal has setVertexBytes method to quickly send
    // intrinsic constants to vertex shader without any buffer. But Dawn doesn't have similar
    // capability. So we have to use WriteBuffer(), and this method is not allowed to be called when
    // there is an active render pass.
    SkASSERT(!cb->hasActivePassEncoder());

    const Caps* caps = fResourceProvider->dawnSharedContext()->caps();
    const uint32_t stride =
            SkAlignTo(intrinsicValues.size(), caps->requiredUniformBufferAlignment());
    // In any one of the following cases, we need to create a new buffer:
    //     (1) There is no current buffer.
    //     (2) The current buffer is full.
    if (!fCurrentBuffer || fCurrentBuffer->slotsUsed() == IntrinsicBuffer::kNumSlots) {
        // We can just replace the current buffer; any prior buffer was already tracked in the LRU
        // list and the intrinsic constants were written directly to the Dawn queue.
        DawnResourceProvider* resourceProvider = fResourceProvider;
        auto dawnBuffer =
                resourceProvider->findOrCreateDawnBuffer(stride * IntrinsicBuffer::kNumSlots,
                                                         BufferType::kUniform,
                                                         AccessPattern::kGpuOnly,
                                                         "IntrinsicConstantBuffer");
        if (!dawnBuffer) {
            // If we failed to create a GPU buffer to hold the intrinsic uniforms, we will fail the
            // Recording being inserted, so return an empty bind info.
            return {};
        }

        fCurrentBuffer = new IntrinsicBuffer(dawnBuffer);
        fIntrinsicBuffersLRU.addToHead(fCurrentBuffer);
        fNumBuffers++;
        // If we have too many buffers, remove the least used one.
        if (fNumBuffers > kMaxNumBuffers) {
            auto* tail = fIntrinsicBuffersLRU.tail();
            fIntrinsicBuffersLRU.remove(tail);
            fPendingIntrinsicBuffers.addToHead(tail);
            fNumBuffers--;
        }
    }

    SkASSERT(fCurrentBuffer && fCurrentBuffer->slotsUsed() < IntrinsicBuffer::kNumSlots);
    uint32_t newOffset = (fCurrentBuffer->slotsUsed()) * stride;
    fResourceProvider->dawnSharedContext()->queue().WriteBuffer(
            fCurrentBuffer->buffer()->dawnBuffer(),
            newOffset,
            intrinsicValues.data(),
            intrinsicValues.size());

    // Track the intrinsic values in the buffer.
    fCurrentBuffer->trackIntrinsic(intrinsicValues, newOffset);

    cb->trackResource(fCurrentBuffer->buffer());
    fCurrentBuffer->updateAccessTime();

    return {fCurrentBuffer->buffer().get(), newOffset, SkTo<uint32_t>(intrinsicValues.size())};
}

template <typename T>
void DawnResourceProvider::IntrinsicConstantsManager::purgeBuffersUntilDoneOrFalse(T pred) {
    using Iter = SkTInternalLList<IntrinsicBuffer>::Iter;
    Iter iter;
    auto* curr = iter.init(fIntrinsicBuffersLRU, Iter::kHead_IterStart);
    while (curr != nullptr) {
        auto* next = iter.next();
        if (pred(curr)) {
            fIntrinsicBuffersLRU.remove(curr);
            fNumBuffers--;
            delete curr;
        } else {
            // If 'pred' returns false, we stop the process of purging buffers.
            return;
        }
        curr = next;
    }
}

// DawnResourceProvider::IntrinsicConstantsManager
// ----------------------------------------------------------------------------

// DawnResourceProvider::BlitWithDrawEncoder
DawnResourceProvider::BlitWithDrawEncoder::BlitWithDrawEncoder(wgpu::RenderPipeline pipeline,
                                                             bool srcIsMSAA)
        : fPipeline(std::move(pipeline)), fSrcIsMSAA(srcIsMSAA) {}

void DawnResourceProvider::BlitWithDrawEncoder::EncodeBlit(
        const wgpu::Device& device,
        const wgpu::RenderPassEncoder& renderEncoder,
        const wgpu::TextureView& srcTextureView,
        const SkIPoint& srcOffset,
        const SkIRect& dstBounds) {
    SkASSERT(fPipeline);
    renderEncoder.SetPipeline(fPipeline);

    // TODO(b/260368758): cache single texture's bind group creation.
    wgpu::BindGroupEntry entry;
    entry.binding = fSrcIsMSAA ? 1 : 0;
    entry.textureView = srcTextureView;

    wgpu::BindGroupDescriptor desc;
    desc.layout = fPipeline.GetBindGroupLayout(0);
    desc.entryCount = 1;
    desc.entries = &entry;

    auto bindGroup = device.CreateBindGroup(&desc);

    renderEncoder.SetBindGroup(0, bindGroup);

    renderEncoder.SetScissorRect(
            dstBounds.left(), dstBounds.top(), dstBounds.width(), dstBounds.height());
    renderEncoder.SetViewport(
            dstBounds.left(), dstBounds.top(), dstBounds.width(), dstBounds.height(), 0, 1);

    // In fragment shader, the sampling coords are calculated as:
    // - x = fragPosition.x - dstX + srcX = fragPosition.x - (dxtX - srcX)
    // - y = fragPosition.y - dstY + srcX = fragPosition.y - (dxtY - srcY)
    int32_t deltaX = dstBounds.left() - srcOffset.x();
    int32_t deltaY = dstBounds.top() - srcOffset.y();
    // Since texture's sizes are never larger than 16 bits, we can encode the offsets's (x, y)
    // in one single 32 bits instance index value. In future, once push constants are implemented in
    // Dawn, we should use them instead.
    SkASSERT(std::abs(deltaX) < std::numeric_limits<int16_t>::max());
    SkASSERT(std::abs(deltaY) < std::numeric_limits<int16_t>::max());
    int32_t baseInstance = (deltaX & 0xffff) | (deltaY << 16);

    // NOTE(b/457887457): need to cast baseInstance to uint32_t explicitly otherwise it would cause
    // TypeError in emscripten, because baseInstance value could be negative in signed integer
    // representation.
    renderEncoder.Draw(/*vertexCount=*/3,
                       /*instanceCount=*/ 1,
                       /*firstVertex=*/0,
                       /*firstInstance=*/static_cast<uint32_t>(baseInstance));
}

// ----------------------------------------------------------------------------
DawnResourceProvider::DawnResourceProvider(SharedContext* sharedContext,
                                           SingleOwner* singleOwner,
                                           uint32_t recorderID,
                                           size_t resourceBudget)
        : ResourceProvider(sharedContext, singleOwner, recorderID, resourceBudget)
        , fSingleOwner(singleOwner) {
    fIntrinsicConstantsManager = std::make_unique<IntrinsicConstantsManager>(this);

    // Only used for debug asserts so this avoids compile errors.
    (void)fSingleOwner;
}

DawnResourceProvider::~DawnResourceProvider() = default;

DawnResourceProvider::BlitWithDrawEncoder DawnResourceProvider::findOrCreateBlitWithDrawEncoder(
        const RenderPassDesc& renderPassDesc, SampleCount srcSampleCount) {
    // Currently Dawn only supports k1 and k4. So we can optimize the pipeline key by specifying
    // whether the source has MSAA or not.
    SkASSERT(srcSampleCount == SampleCount::k1 || srcSampleCount == SampleCount::k4);
    const bool srcIsMSAA = srcSampleCount > SampleCount::k1;
    const uint32_t pipelineKey = this->dawnSharedContext()->dawnCaps()->getRenderPassDescKeyForPipeline(
            renderPassDesc, srcIsMSAA);
    wgpu::RenderPipeline pipeline = fBlitWithDrawPipelines[pipelineKey];
    if (!pipeline) {
        // Since texture's sizes are never larger than 16 bits, we can encode the offsets's (x, y)
        // in one single 32 bits instance index value.
        static constexpr char kShaderSrc[] =
            "struct VertexOutput {"
                "@builtin(position) position: vec4f,"
                "@location(1) @interpolate(flat, either) srcOffset: vec2i,"
            "};"
            "var<private> fullscreenTriPositions : array<vec2<f32>, 3> = array<vec2<f32>, 3>("
                "vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));"

            "@vertex "
            "fn VS(@builtin(vertex_index) vertexIndex : u32,"
                  "@builtin(instance_index) instanceIndex : u32)"
                  "-> VertexOutput {"
                "var out: VertexOutput;"
                "out.position = vec4(fullscreenTriPositions[vertexIndex], 1.0, 1.0);"
                "var srcOffset = vec2u("
                    "bitcast<u32>(instanceIndex & 0xffff),"
                    "bitcast<u32>(instanceIndex >> 16)"
                ");"

                // Sign extending from 16 bits to 32 bits
                "let hasSignBit = (srcOffset & vec2u(0x8000)) != vec2u(0u);"
                "srcOffset = select(srcOffset, srcOffset | vec2u(0xffff0000), hasSignBit);"

                "out.srcOffset = bitcast<vec2i>(srcOffset);"

                "return out;"
            "}"

            "fn getSamplingCoords(input: VertexOutput) -> vec2i {"
                "var coords : vec2<i32> = vec2<i32>(i32(input.position.x), i32(input.position.y));"
                "return coords - input.srcOffset;"
            "}"

            "@group(0) @binding(0) var colorMap: texture_2d<f32>;"
            "@fragment "
            "fn SampleFS(input: VertexOutput) -> @location(0) vec4<f32> {"
                "let coords = getSamplingCoords(input);"
                "return textureLoad(colorMap, coords, 0);"
            "}"

            "@group(0) @binding(1) var msColorMap: texture_multisampled_2d<f32>;"
            "@fragment\n"
            "fn SampleMSAAFS(input: VertexOutput) -> @location(0) vec4<f32> {"
                "let coords = getSamplingCoords(input);"
                "const sampleCount = %u;"
                "var sum = vec4f(0.0);"
                "for (var i: u32 = 0; i < sampleCount; i = i + 1) {"
                    "sum += textureLoad(msColorMap, coords, i);"
                "}"
                "return sum * (1.0 / f32(sampleCount));"
            "}";

        auto shaderModule = create_shader_module(
                dawnSharedContext()->device(),
                SkStringPrintf(kShaderSrc, (unsigned) srcSampleCount).c_str());

        pipeline = create_blit_render_pipeline(
                dawnSharedContext(),
                /*label=*/"BlitWithDraw",
                std::move(shaderModule),
                "VS",
                srcIsMSAA ? "SampleMSAAFS": "SampleFS",
                /*renderPassColorFormat=*/
                TextureFormatToDawnFormat(renderPassDesc.fColorAttachment.fFormat),
                /*renderPassDepthStencilFormat=*/
                TextureFormatToDawnFormat(renderPassDesc.fDepthStencilAttachment.fFormat),
                renderPassDesc.fColorAttachment.fSampleCount);

        if (pipeline) {
            fBlitWithDrawPipelines.set(pipelineKey, pipeline);
        }
    }

    return BlitWithDrawEncoder(std::move(pipeline), srcIsMSAA);
}

sk_sp<Texture> DawnResourceProvider::onCreateWrappedTexture(const BackendTexture& texture,
                                                            std::string_view label) {
    // Convert to smart pointers. wgpu::Texture* constructor will increment the ref count.
    wgpu::Texture dawnTexture         = BackendTextures::GetDawnTexturePtr(texture);
    wgpu::TextureView dawnTextureView = BackendTextures::GetDawnTextureViewPtr(texture);
    SkASSERT(!dawnTexture || !dawnTextureView);

    if (!dawnTexture && !dawnTextureView) {
        return {};
    }

    if (dawnTexture) {
        return DawnTexture::MakeWrapped(this->dawnSharedContext(),
                                        texture.dimensions(),
                                        texture.info(),
                                        std::move(dawnTexture),
                                        label);
    } else {
        return DawnTexture::MakeWrapped(this->dawnSharedContext(),
                                        texture.dimensions(),
                                        texture.info(),
                                        std::move(dawnTextureView),
                                        label);
    }
}

sk_sp<DawnTexture> DawnResourceProvider::findOrCreateDiscardableMSAALoadTexture(
        SkISize dimensions, const TextureInfo& msaaInfo) {
    SkASSERT(msaaInfo.isValid());

    // Derive the load texture's info from MSAA texture's info.
    DawnTextureInfo dawnMsaaLoadTextureInfo = TextureInfoPriv::Get<DawnTextureInfo>(msaaInfo);
    dawnMsaaLoadTextureInfo.fSampleCount = SampleCount::k1;
    dawnMsaaLoadTextureInfo.fUsage |= wgpu::TextureUsage::TextureBinding;

#if !defined(__EMSCRIPTEN__)
    // MSAA texture can be transient attachment (memoryless) but the load texture cannot be.
    // This is because the load texture will need to have its content retained between two passes
    // loading:
    // - first pass: the resolve texture is blitted to the load texture.
    // - 2nd pass: the actual render pass is started and the load texture is blitted to the MSAA
    // texture.
    dawnMsaaLoadTextureInfo.fUsage &= (~wgpu::TextureUsage::TransientAttachment);
#endif

    auto texture = this->findOrCreateShareableTexture(
            dimensions,
            TextureInfos::MakeDawn(dawnMsaaLoadTextureInfo),
            "DiscardableLoadMSAATexture");

    return sk_sp<DawnTexture>(static_cast<DawnTexture*>(texture.release()));
}

sk_sp<ComputePipeline> DawnResourceProvider::createComputePipeline(
        const ComputePipelineDesc& desc) {
    return DawnComputePipeline::Make(this->dawnSharedContext(), desc);
}

sk_sp<Texture> DawnResourceProvider::createTexture(
        SkISize dimensions, const TextureInfo& info, std::string_view label) {
    return DawnTexture::Make(this->dawnSharedContext(), dimensions, info, label);
}

sk_sp<Buffer> DawnResourceProvider::createBuffer(size_t size,
                                                 BufferType type,
                                                 AccessPattern accessPattern,
                                                 std::string_view label) {
    return DawnBuffer::Make(this->dawnSharedContext(), size, type, accessPattern, label);
}

sk_sp<Sampler> DawnResourceProvider::createSampler(const SamplerDesc& samplerDesc) {
    return DawnSampler::Make(this->dawnSharedContext(), samplerDesc);
}

BackendTexture DawnResourceProvider::onCreateBackendTexture(SkISize dimensions,
                                                            const TextureInfo& info) {
    wgpu::Texture texture = DawnTexture::MakeDawnTexture(this->dawnSharedContext(),
                                                         dimensions,
                                                         info);
    if (!texture) {
        return {};
    }

    return BackendTextures::MakeDawn(texture.MoveToCHandle());
}

void DawnResourceProvider::onDeleteBackendTexture(const BackendTexture& texture) {
    SkASSERT(texture.isValid());
    SkASSERT(texture.backend() == BackendApi::kDawn);

    // Automatically release the pointers in wgpu::TextureView & wgpu::Texture's dtor.
    // Acquire() won't increment the ref count.
    wgpu::TextureView::Acquire(BackendTextures::GetDawnTextureViewPtr(texture));
    // We need to explicitly call Destroy() here since since that is the recommended way to delete
    // a Dawn texture predictably versus just dropping a ref and relying on garbage collection.
    //
    // Additionally this helps to work around an issue where Skia may have cached a BindGroup that
    // references the underlying texture. Skia currently doesn't destroy BindGroups when its use of
    // the texture goes away, thus a ref to the texture remains on the BindGroup and memory is never
    // cleared up unless we call Destroy() here.
    wgpu::Texture::Acquire(BackendTextures::GetDawnTexturePtr(texture)).Destroy();
}

DawnSharedContext* DawnResourceProvider::dawnSharedContext() const {
    return static_cast<DawnSharedContext*>(fSharedContext);
}

sk_sp<DawnBuffer> DawnResourceProvider::findOrCreateDawnBuffer(size_t size,
                                                               BufferType type,
                                                               AccessPattern accessPattern,
                                                               std::string_view label) {
    sk_sp<Buffer> buffer = this->findOrCreateNonShareableBuffer(size, type, accessPattern, label);
    DawnBuffer* ptr = static_cast<DawnBuffer*>(buffer.release());
    return sk_sp<DawnBuffer>(ptr);
}

const wgpu::Buffer& DawnResourceProvider::getOrCreateNullBuffer() {
    if (!fNullBuffer) {
        wgpu::BufferDescriptor desc;
        if (fSharedContext->caps()->setBackendLabels()) {
            desc.label = "UnusedBufferSlot";
        }
        desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform |
                     wgpu::BufferUsage::Storage;
        desc.size = kBufferBindingSizeAlignment;
        desc.mappedAtCreation = false;

        fNullBuffer = this->dawnSharedContext()->device().CreateBuffer(&desc);
        SkASSERT(fNullBuffer);
    }

    return fNullBuffer;
}

const wgpu::TextureView& DawnResourceProvider::getOrCreateNullTextureView() {
    if (!fNullTextureView) {
        wgpu::TextureDescriptor desc;
        if (fSharedContext->caps()->setBackendLabels()) {
            desc.label = "UnusedTextureSlot";
        }
        desc.usage = wgpu::TextureUsage::TextureBinding;
        desc.dimension = wgpu::TextureDimension::e2D;
        desc.size = {1, 1, 1};
        desc.format = TextureFormatToDawnFormat(StorageContext::kTextureFormat);
        desc.mipLevelCount = 1;
        desc.sampleCount = 1;

        wgpu::Texture nullTexture = this->dawnSharedContext()->device().CreateTexture(&desc);
        if (nullTexture) {
            fNullTextureView = nullTexture.CreateView();
        }
        SkASSERT(fNullTextureView);
    }

    return fNullTextureView;
}

wgpu::BindGroup DawnResourceProvider::createBindGroup(SkSpan<wgpu::BindGroupEntry> entries,
                                                      const wgpu::BindGroupLayout layout) {
    const auto& device = this->dawnSharedContext()->device();

    wgpu::BindGroupDescriptor desc;
    desc.layout = layout;
    desc.entryCount = entries.size();
    desc.entries = entries.data();

    return device.CreateBindGroup(&desc);
}

wgpu::BindGroup DawnResourceProvider::findOrCreateSingleUniformBindGroup(
        const BindBufferInfo& bufferInfo) {
    SKGPU_ASSERT_SINGLE_OWNER(fSingleOwner)
    // We should only hit the single-uniform case if push constant usage is supported for intrinsic
    // constants.
    SkASSERT(this->dawnSharedContext()->dawnCaps()->
            resourceBindingRequirements().fUsePushConstantsForIntrinsicConstants);

    auto buffer = static_cast<const DawnBuffer*>(bufferInfo.fBuffer);

    if (auto cachedBindGroup = buffer->getCachedSingleBufferBindGroup(bufferInfo.fSize)) {
        return *cachedBindGroup;
    }

    // We should be able to assume that if we only have one uniform that it is the combined uniform
    // buffer. Construct a list of bind group entries to represent the single combined uniform
    // buffer case.
    wgpu::BindGroupEntry intrinsicConstantNullEntry;
    intrinsicConstantNullEntry.binding = DawnGraphicsPipeline::kIntrinsicUniformBufferIndex;
    intrinsicConstantNullEntry.buffer  = this->getOrCreateNullBuffer();

    wgpu::BindGroupEntry combinedUniformEntry;
    combinedUniformEntry.binding = DawnGraphicsPipeline::kCombinedUniformIndex;
    combinedUniformEntry.offset  = 0; // Use dynamic offsets; ignore bufferInfo.fOffset
    combinedUniformEntry.buffer  = buffer->dawnBuffer();
    combinedUniformEntry.size    = SkAlignTo(bufferInfo.fSize, kBufferBindingSizeAlignment);

    wgpu::BindGroupEntry storageBufferNullEntry;
    storageBufferNullEntry.binding = DawnGraphicsPipeline::kStorageBufferIndex;
    if (this->dawnSharedContext()->caps()->storageBufferSupport()) {
        storageBufferNullEntry.buffer = this->getOrCreateNullBuffer();
    } else {
        storageBufferNullEntry.textureView = this->getOrCreateNullTextureView();
    }

    std::array<wgpu::BindGroupEntry, kNumUniformEntries> entries = {
        intrinsicConstantNullEntry,
        combinedUniformEntry,
        storageBufferNullEntry
    };

    wgpu::BindGroup bindGroup = this->createBindGroup(
            entries,
            this->dawnSharedContext()->getUniformBuffersBindGroupLayout(wgpu::ShaderStage::None));

    buffer->addCachedSingleBufferBindGroup(bindGroup, bufferInfo.fSize);

    return bindGroup;
}


wgpu::BindGroup DawnResourceProvider::findOrCreateSingleTextureSamplerBindGroup(
        const DawnSampler* sampler, const DawnTexture* texture) {
    SKGPU_ASSERT_SINGLE_OWNER(fSingleOwner)

    // First check if we already have a cached bind group we can use.
    auto cachedBindGroup = texture->getCachedSingleTextureBindGroup(sampler);
    if (cachedBindGroup) {
        return *cachedBindGroup;
    }

    // Otherwise, create one and store it on the Texture for potential future reuse.
    std::array<wgpu::BindGroupEntry, 2> entries;
    entries[0].binding = 0;
    entries[0].sampler = sampler->dawnSampler();
    entries[1].binding = 1;
    entries[1].textureView = texture->sampleTextureView();

    wgpu::BindGroup bindGroup = this->createBindGroup(
            entries, this->dawnSharedContext()->getSingleTextureSamplerBindGroupLayout());
    texture->addCachedSingleTextureBindGroup(bindGroup, sampler);

    return bindGroup;
}

void DawnResourceProvider::onFreeGpuResources() {
    SKGPU_ASSERT_SINGLE_OWNER(fSingleOwner)

    fIntrinsicConstantsManager->freeGpuResources();
}

void DawnResourceProvider::onPurgeResourcesNotUsedSince(
        StdSteadyClock::time_point purgeTime,
        std::optional<StdSteadyClock::time_point> quitPurgingTime) {
    fIntrinsicConstantsManager->purgeResourcesNotUsedSince(purgeTime, quitPurgingTime);
}

BindBufferInfo DawnResourceProvider::findOrCreateIntrinsicBindBufferInfo(
        DawnCommandBuffer* cb, UniformDataBlock intrinsicValues) {
    return fIntrinsicConstantsManager->add(cb, intrinsicValues);
}

void DawnResourceProvider::releasePendingIntrinsicBuffers() {
    fIntrinsicConstantsManager->releasePendingIntrinsicBuffers();
}

DawnThreadSafeResourceProvider::DawnThreadSafeResourceProvider(
        std::unique_ptr<ResourceProvider> resourceProvider)
    : ThreadSafeResourceProvider(std::move(resourceProvider)) {}

} // namespace skgpu::graphite
