/*
 * Copyright 2021 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/buffer/BufferManager.h"

#include "include/gpu/GpuTypes.h"
#include "include/gpu/graphite/Recording.h"
#include "include/private/SkAlign.h"
#include "include/private/SkAssert.h"
#include "include/private/SkAttributes.h"
#include "include/private/SkLog.h"
#include "include/private/SkMath.h"
#include "include/private/SkTo.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/GlobalCache.h"
#include "src/gpu/graphite/QueueManager.h"
#include "src/gpu/graphite/RecordingPriv.h"
#include "src/gpu/graphite/Resource.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/buffer/UploadBufferManager.h"
#include "src/gpu/graphite/task/ClearBuffersTask.h"
#include "src/gpu/graphite/task/CopyTask.h"
#include "src/gpu/graphite/task/Task.h"
#include "src/gpu/graphite/task/TaskList.h"

#include <algorithm>
#include <cstddef>
#include <cstring>
#include <limits>
#include <numeric>
#include <tuple>

namespace skgpu::graphite {

namespace {

// The limit for all data created by the StaticBufferManager. This data remains alive for
// the entire SharedContext so we want to keep it small and give a concrete upper bound to
// clients for our steady-state memory usage.
// FIXME The current usage is 6308 bytes across static vertex and index buffers, but that includes
// multiple copies of tessellation data, and an unoptimized AnalyticRRect mesh. Once those issues
// are addressed, we can tighten this and decide on the transfer buffer sizing as well.
[[maybe_unused]] static constexpr uint32_t kMaxStaticDataSize = 7 << 10;

// Helpers for creating a BufferState based on type, options, and caps

AccessPattern get_gpu_access_pattern(bool isGpuOnlyAccess, const DrawBufferManager::Options& opts) {
    if (isGpuOnlyAccess) {
#if defined(GPU_TEST_UTILS)
        if (opts.fAllowCopyingGpuOnly) {
            return AccessPattern::kGpuOnlyCopySrc;
        }
#endif
        return AccessPattern::kGpuOnly;
    } else {
        return AccessPattern::kHostVisible;
    }
}

// This returns the minimum required alignment depending on the type of buffer. This is guaranteed
// to be a power of two.
uint32_t minimum_alignment(BufferType type, bool useTransferBuffers, const Caps* caps) {
    uint32_t alignment = 4;
    if (type == BufferType::kUniform) {
        alignment = SkTo<uint32_t>(caps->requiredUniformBufferAlignment());
    } else if (type == BufferType::kStorage || type == BufferType::kVertexStorage ||
               type == BufferType::kIndexStorage || type == BufferType::kIndirect) {
        alignment = SkTo<uint32_t>(caps->requiredStorageBufferAlignment());
    }
    if (useTransferBuffers) {
        // Both alignment and the requiredTransferBufferAlignment must be powers of two, so max
        // provides the correct alignment semantics
        alignment = std::max(alignment, SkTo<uint32_t>(caps->requiredTransferBufferAlignment()));
    }
    return alignment;
}

uint32_t min_block_size(BufferType type,
                        uint32_t minAlignment,
                        const DrawBufferManager::Options& opts) {
    uint32_t size;
    if (type == BufferType::kIndex || type == BufferType::kIndexStorage) {
        size = opts.fIndexBufferSize;
    } else if (type == BufferType::kVertex || type == BufferType::kVertexStorage) {
        size = opts.fVertexBufferMinSize;
    } else {
        size = opts.fStorageBufferMinSize;
    }
#if defined(GPU_TEST_UTILS)
    if (opts.fUseExactBuffSizes) {
        return size; // No extra alignment
    }
#endif

    return SkAlignTo(size, minAlignment);
}

uint32_t max_block_size(BufferType type,
                        uint32_t minAlignment,
                        const DrawBufferManager::Options& opts) {
#if defined(GPU_TEST_UTILS)
    if (opts.fUseExactBuffSizes) {
        // Clamp to the minimum size
        return min_block_size(type, minAlignment, opts);
    }
#endif

    uint32_t size;
    if (type == BufferType::kIndex || type == BufferType::kIndexStorage) {
        size = opts.fIndexBufferSize;
    } else if (type == BufferType::kVertex || type == BufferType::kVertexStorage) {
        size = opts.fVertexBufferMaxSize;
    } else {
        size = opts.fStorageBufferMaxSize;
    }

    return SkAlignTo(size, minAlignment);
}

} // anonymous namespace

// ------------------------------------------------------------------------------------------------
// BufferSubAllocator

BufferSubAllocator::BufferSubAllocator(DrawBufferManager* owner,
                                       int stateIndex,
                                       sk_sp<Buffer> buffer,
                                       BindBufferInfo transferBuffer,
                                       void* mappedPtr,
                                       size_t stride)
        : fOwner(owner)
        , fStateIndex(stateIndex)
        , fBuffer(std::move(buffer))
        , fTransferBuffer(transferBuffer)
        , fMappedPtr(mappedPtr)
        , fOffset(0)
        , fStride(SkTo<uint32_t>(stride)) {
    // A starting offset of 0 means we don't need to explicitly lookup the minimum binding alignment
    // since the first sub-allocation is automatically aligned.
    if (fBuffer && fStride > 0 && fStride <= fBuffer->size()) {
        // This puts the BufferSubAllocator in the same state as prepForStride(stride, *)
        fRemaining = SkTo<uint32_t>(fBuffer->size()) / fStride;
    } else {
        fRemaining = 0;
    }

    SkASSERT(fStride != 0);
}

BufferSubAllocator& BufferSubAllocator::operator=(BufferSubAllocator&& other) {
    if (this == &other) {
        return *this; // no-op moving into itself
    }

    // Reset the destination allocator first since other's contents will overwrite whatever came
    // beforehand and that must go back to the manager.
    this->reset();

    // Copy fields
    fOwner = other.fOwner;
    fStateIndex = other.fStateIndex;
    fTransferBuffer = other.fTransferBuffer;
    fMappedPtr = other.fMappedPtr;
    fOffset = other.fOffset;
    fStride = other.fStride;
    fRemaining = other.fRemaining;

    // Move buffer (leaving other in an invalid state)
    fBuffer = std::move(other.fBuffer);
    SkASSERT(!other);
    return *this;
}

void BufferSubAllocator::prepForStride(size_t stride, size_t align, size_t minCount,
                                       size_t headroom) {
    SkASSERT(stride > 0 && align > 0); // Expect valid inputs
    if (fBuffer) {
        if (fStride == stride && (align == 1 || align == stride)) {
            // Shortcut if we're already aligned with the last call to prepForStride().
            // Leave fRemaining alone, it's either enough for minCount or not, but reserve() will
            // do the right thing regardless.
            SkASSERT(fOffset % align == 0);
            SkASSERT(fOffset % stride == 0);
            return;
        }

        // On re-aligning to a new stride, the offset needs to be aligned to the LCM of `align` and
        // `stride` so that repeated suballocations of `stride` can be performed by simply adding to
        // fOffset without additional instructions. If `fStride == 0`, it's a signal that the first
        // offset also needs to be aligned to the minimum binding requirement.
        uint32_t align32 = BufferAligner::LcmAlignment(SkTo<uint32_t>(align), SkTo<uint32_t>(stride));
        if (fStride == 0) {
            const uint32_t minAlignment = fOwner->fCurrentBuffers[fStateIndex].fMinAlignment;
            align32 = BufferAligner::LcmAlignment(minAlignment, align32);
        }

        const uint32_t stride32 = SkTo<uint32_t>(stride);
        const uint32_t headroom32 = SkTo<uint32_t>(headroom);
        const uint32_t reserveForHeadroom = headroom32 > stride32 ? headroom32 - stride32 : 0;
        // Ensures we won't overflow fOffset past buffer size once we align it
        if (this->remainingBytes() >= align32 - 1 + reserveForHeadroom) {
            const uint32_t offset = SkAlignNonPow2(fOffset, align32);
            SkASSERT(offset + reserveForHeadroom <= fBuffer->size());
            fStride = stride32;
            fRemaining = (SkTo<uint32_t>(fBuffer->size()) - offset - reserveForHeadroom) / fStride;
            if (fRemaining > 0 && fRemaining >= minCount) {
                // Successful prep, so preserve the aligned offset
                fOffset = offset;
                return;
            }
        }
    }

    // If we've reached here, there wasn't a buffer or enough room to align, or enough room to
    // satisfy minCount, so set fRemaining=0 to fail subsequent reservations.
    fRemaining = 0;
}

void BufferSubAllocator::reset() {
    if (fBuffer) {
        SkASSERT(fOwner);

        if (fOwner->fMappingFailed) {
            fBuffer = nullptr;
            fRemaining = 0;
            fTransferBuffer = {};
            return;
        }

        DrawBufferManager::BufferState& state = fOwner->fCurrentBuffers[fStateIndex];
        if (fBuffer->shareable() == Shareable::kScratch) {
            // TODO: Merge this reuse of scratch resources with the ScratchResourceManager, but
            // currently this is resolved outside of Task::prepareResources().

            // The scratch buffer's availability for reuse (scoped to the owning DrawBufferManager)
            // was tied to this BufferSubAllocator, so when that is reset, we just remove the buffer
            // from the set of unavailable buffers.
            SkASSERT(state.fUnavailableScratchBuffers.contains(fBuffer.get()));
            state.fUnavailableScratchBuffers.remove(fBuffer.get());

            SkASSERT(!fTransferBuffer); // Scratch buffers shouldn't be using transfer buffers
            fOwner->fUsedBuffers.emplace_back(std::move(fBuffer), BindBufferInfo{});
        } else if (state.fAvailableBuffer.fBuffer.get() == fBuffer.get() || // can't stash itself
                   this->remainingBytes() < state.fAvailableBuffer.remainingBytes() || // too small
                   this->remainingBytes() < state.fMinAlignment) { // basically empty
            // Transfer ownership of the buffer (and any transfer buffer) back to the manager, using
            // the current offset as a more restricted limit for copying.
            if (fTransferBuffer) {
                // This alignment ensures we are copying a subset that still respects xfer alignment
                fTransferBuffer.fSize = SkAlignTo(fOffset, state.fMinAlignment);
            }
            fOwner->fUsedBuffers.emplace_back(std::move(fBuffer), fTransferBuffer);
        } else {
            // Save this buffer for later, which leaves this instance empty and resets the prior
            // value of fAvailableBuffer (which then goes through the true branch of this if).
            state.fAvailableBuffer = std::move(*this);
        }

        fRemaining = 0;
        SkASSERT(!fBuffer);
    } // else nothing to reset
}

// ------------------------------------------------------------------------------------------------
// DrawBufferManager::BufferState

DrawBufferManager::BufferState::BufferState(BufferType type,
                                            const char* label,
                                            bool isGpuOnly,
                                            const Options& opts,
                                            const Caps* caps)
        : fType(type)
        // The buffer can be GPU-only if
        //     a) the caller does not intend to ever upload CPU data to the buffer; or
        //     b) CPU data will get uploaded to fBuffer only via a transfer buffer
        , fAccessPattern(get_gpu_access_pattern(isGpuOnly || !caps->drawBufferCanBeMapped(), opts))
        , fUseTransferBuffer(!isGpuOnly && !caps->drawBufferCanBeMapped())
        , fLabel(label)
        , fMinAlignment(minimum_alignment(type, fUseTransferBuffer, caps))
        , fMinBlockSize(min_block_size(type, fMinAlignment, opts))
        , fMaxBlockSize(max_block_size(type, fMinAlignment, opts)) {
    SkASSERT(SkIsPow2(fMinAlignment));
    SkASSERT(fMinBlockSize <= fMaxBlockSize);
}

sk_sp<Buffer> DrawBufferManager::BufferState::findOrCreateBuffer(ResourceProvider* provider,
                                                                 Shareable shareable,
                                                                 uint32_t byteCount) {
    if (shareable == Shareable::kScratch) {
        sk_sp<Buffer> scratchBuffer = provider->findOrCreateScratchBuffer(
                byteCount, fType, fAccessPattern, fLabel, fUnavailableScratchBuffers);
        if (scratchBuffer) {
            fUnavailableScratchBuffers.add(scratchBuffer.get());
        }
        return scratchBuffer;
    } else {
        return provider->findOrCreateNonShareableBuffer(byteCount, fType, fAccessPattern, fLabel);
    }
}

// ------------------------------------------------------------------------------------------------
// DrawBufferManager

DrawBufferManager::DrawBufferManager(ResourceProvider* resourceProvider,
                                     const Caps* caps,
                                     UploadBufferManager* uploadManager,
                                     Options dbmOpts)
        : fResourceProvider(resourceProvider)
        , fCaps(caps)
        , fUploadManager(uploadManager)
        , fCurrentBuffers{{
            // Mappable buffers
            {BufferType::kVertex, "VertexBuffer", /*isGpuOnly=*/false, dbmOpts, caps},
            {BufferType::kIndex, "IndexBuffer", /*isGpuOnly=*/false, dbmOpts, caps},
            {BufferType::kUniform, "UniformBuffer", /*isGpuOnly=*/false, dbmOpts, caps},
            {BufferType::kStorage, "StorageBuffer", /*isGpuOnly=*/false, dbmOpts, caps},
            // GPU-only buffers
            {BufferType::kStorage, "GPUOnlyStorageBuffer", /*isGpuOnly=*/true, dbmOpts, caps},
            {BufferType::kVertexStorage, "VertexStorageBuffer", /*isGpuOnly=*/true, dbmOpts, caps},
            {BufferType::kIndexStorage, "IndexStorageBuffer", /*isGpuOnly=*/true, dbmOpts, caps},
            {BufferType::kIndirect, "IndirectStorageBuffer", /*isGpuOnly=*/true, dbmOpts, caps}}} {}

DrawBufferManager::~DrawBufferManager() {
    // Must reset these *before* we are deleted
    for (auto& b : fCurrentBuffers) {
        b.fAvailableBuffer.reset();
    }
}

void DrawBufferManager::onFailedBuffer() {
    fMappingFailed = true;

    // Clean up and unmap everything now
    fClearList.clear();
    for (auto& state : fCurrentBuffers) {
        state.fAvailableBuffer.reset();
         // We aren't allocating anything anymore so don't maintain this list. Their outstanding
         // BufferSubAllocators will have a no-op when they get reset.
        state.fUnavailableScratchBuffers.reset();
        state.fLastBufferSize = 0;
    }

    for (auto& [buffer, _] : fUsedBuffers) {
        if (buffer->isMapped()) {
            buffer->unmap();
        }
    }
    fUsedBuffers.clear();
}

bool DrawBufferManager::transferToRecording(Recording* recording) {
    if (fMappingFailed) {
        // All state should have been reset by onFailedBuffer() except for this error flag.
        SkASSERT(fUsedBuffers.empty() && fClearList.empty());
#if defined(SK_DEBUG)
        for (const auto& state : fCurrentBuffers) {
            SkASSERT(!SkToBool(state.fAvailableBuffer));
            SkASSERT(state.fUnavailableScratchBuffers.empty());
        }
#endif

        fMappingFailed = false;
        return false;
    }

    for (auto& state : fCurrentBuffers) {
        // Reset all available buffer sub allocators since they won't be allocatable anymore.
        // This pushes the underlying resource and transfer range to fUsedBuffers
        state.fAvailableBuffer.reset();
        // BufferSubAllocators should have gone out of scope well before Recorder::snap() is called.
        SkASSERT(state.fUnavailableScratchBuffers.empty());

        // We reset the last buffer size back to 0 to keep the buffer growth behavior the same
        // across calls to snap(). If we knew every snap() would be approximately the same workload,
        // we could choose to keep the last alloc size as-is so that subsequent frames create
        // fewer buffers. We choose *not* to do this because:
        //  - Chrome often snaps Recordings with disparate workloads within a frame (e.g. tile vs
        //    canvas2d) and we don't want to overallocate on a small recording.
        //  - It obfuscates the performance cost of the first frame if we reach a steady state that
        //    requires no additional buffer allocations.
        // We could choose to reduce fLastBufferSize (e.g. halve it) to get a head start and reduce
        // the potential for over-allocation, but in performance measurements on buffer-heavy scenes
        // this did not lead to measurable improvements. Thus, we reset so every frame is the same.
        state.fLastBufferSize = 0;
    }

    if (!fClearList.empty()) {
        recording->priv().taskList()->add(ClearBuffersTask::Make(std::move(fClearList)));
    }

    for (auto& [buffer, transferBuffer] : fUsedBuffers) {
        if (transferBuffer) {
            SkASSERT(buffer);
            SkASSERT(!fCaps->drawBufferCanBeMapped());
            // Since the transfer buffer is managed by the UploadManager, we don't manually unmap
            // it here or need to pass a ref into CopyBufferToBufferTask.
            size_t copySize = buffer->size();
            recording->priv().taskList()->add(
                    CopyBufferToBufferTask::Make(transferBuffer.fBuffer,
                                                 transferBuffer.fOffset,
                                                 std::move(buffer),
                                                 /*dstOffset=*/0,
                                                 copySize));
        } else {
            if (buffer->isMapped()) {
                buffer->unmap();
            }
            recording->priv().addResourceRef(std::move(buffer));
        }
    }

    fUsedBuffers.clear();

    return true;
}

BufferSubAllocator DrawBufferManager::getBuffer(
        int stateIndex,
        size_t count,
        size_t stride,
        size_t xtraAlignment,
        size_t headroom,
        ClearBuffer cleared,
        Shareable shareable) {
    BufferState& state = fCurrentBuffers[stateIndex];
    // The size for a buffer is aligned to the minimum block size for better resource reuse, which
    // is more conservative than fMinAlignment.
    uint32_t requiredBytes32 = BufferAligner::ValidateCountAndStride(count, stride, headroom,
                                                                     state.fMinBlockSize);
    if (fMappingFailed || !requiredBytes32) {
        return {};
    }

    const bool supportCpuUpload = state.fAccessPattern == AccessPattern::kHostVisible ||
                                  state.fUseTransferBuffer;
    // Shareable buffers must be GPU-only to actually share effectively.
    SkASSERT(shareable == Shareable::kNo || !supportCpuUpload);

    // For non-shareable buffers, we keep the largest relinquished non-shareable buffer in case it
    // has room leftover to be used by future allocations. Scratch buffer ownership is entirely
    // managed by the caller, so always create a new BufferSubAllocator.
    if (shareable == Shareable::kNo) {
        state.fAvailableBuffer.resetForNewBinding(); // ensure we include min binding alignment
        state.fAvailableBuffer.prepForStride(stride, xtraAlignment, count, headroom);
        if (state.fAvailableBuffer.availableWithStride() >= count) {
            SkASSERT(state.fAvailableBuffer.fBuffer);
            SkASSERT(state.fAvailableBuffer.fBuffer->shareable() == shareable);
            SkASSERT(SkToBool(state.fAvailableBuffer.fMappedPtr) == supportCpuUpload);
            return std::move(state.fAvailableBuffer);
        }

        // Not enough room in the available buffer so release it and create a new buffer.
        state.fAvailableBuffer.reset();
    }

    // Create the next buffer by doubling the size of the previous buffer and clamping to be within
    // the min and max block sizes if `requiredBytes` is less than the max. Otherwise, create a
    // buffer large enough to satisfy `requiredBytes` but align it to minBlockSize.
    uint32_t bufferSize = SkAlignTo(requiredBytes32, state.fMinBlockSize);
    if (bufferSize < state.fMaxBlockSize) {
        // fMaxBlockSize should be sufficiently small that there's no risk of overflowing here.
        SkASSERT(std::numeric_limits<uint32_t>::max() /2 > state.fLastBufferSize);
        bufferSize = std::max(bufferSize, std::min(state.fLastBufferSize * 2, state.fMaxBlockSize));
        state.fLastBufferSize = bufferSize;
        SkASSERT(bufferSize <= state.fMaxBlockSize);
    } else {
        // Jump to the max block size for subsequent amortized allocations if we get a really big
        // buffer request.
        state.fLastBufferSize = state.fMaxBlockSize;
    }
    SkASSERT(bufferSize >= requiredBytes32 && bufferSize >= state.fMinBlockSize);

    sk_sp<Buffer> buffer = state.findOrCreateBuffer(fResourceProvider, shareable, bufferSize);
    if (!buffer) {
        this->onFailedBuffer();
        return {};
    }

    BindBufferInfo transferBuffer;
    void* mappedPtr = nullptr;
    if (supportCpuUpload) {
        if (state.fUseTransferBuffer) {
            std::tie(mappedPtr, transferBuffer) = fUploadManager->makeBindInfo(buffer->size(),
                    fCaps->requiredTransferBufferAlignment(), "TransferForDataBuffer");
        } else {
            mappedPtr = buffer->map();
        }

        if (!mappedPtr) {
            this->onFailedBuffer(); // Either transfer buffer failed or direct mapping failed
            return {};
        }
    }

    if (cleared == ClearBuffer::kYes) {
        fClearList.push_back(BindBufferInfo{buffer.get(), 0, bufferSize});
    }

    // The returned buffer is not set to fAvailableBuffer because it is going to be passed up to
    // the caller for their use first. Since a new BufferSubAllocator starts at offset 0, there's no
    // need to account for `xtraAlignment`.
    return BufferSubAllocator(this, stateIndex, std::move(buffer),
                              transferBuffer, mappedPtr, stride);
}

// ------------------------------------------------------------------------------------------------
// StaticBufferManager

StaticBufferManager::StaticBufferManager(ResourceProvider* resourceProvider,
                                         const Caps* caps)
        : fResourceProvider(resourceProvider)
        , fUploadManager(resourceProvider, caps)
        , fRequiredTransferAlignment(SkTo<uint32_t>(caps->requiredTransferBufferAlignment()))
        , fVertexBufferState(BufferType::kVertex, caps)
        , fIndexBufferState(BufferType::kIndex, caps) {}
StaticBufferManager::~StaticBufferManager() = default;

StaticBufferManager::BufferState::BufferState(BufferType type, const Caps* caps)
        : fBufferType(type)
        , fMinimumAlignment(minimum_alignment(type, /*useTransferBuffers=*/true, caps))
        , fTotalRequiredBytes(0) {}

// ARM hardware b/399631317 also means that static vertex data must be padded and zeroed out. So we
// always request a count 4 aligned offset, count 4 aligned amount of space, and zero it.
VertexWriter StaticBufferManager::getVertexWriter(size_t count,
                                                  size_t stride,
                                                  BindBufferInfo* binding) {
    const size_t size = count * stride;
    const size_t alignedCount = SkAlign4(count);
    void* data = this->prepareStaticData(&fVertexBufferState, size, stride * 4, binding);
    if (alignedCount > count) {
        const uint32_t byteDiff = (alignedCount - count) * stride;
        void* zPtr = SkTAddOffset<void>(data, count * stride);
        SK_UNSAFE_TODO(memset(zPtr, 0, byteDiff));
    }
    return VertexWriter{data, size};
}

VertexWriter StaticBufferManager::getIndexWriter(size_t size, BindBufferInfo* binding) {
    // The index writer does not have the same alignment requirements as a vertex, so we simply pass
    // in the minimum alignment as the required alignment
    void* data = this->prepareStaticData(&fIndexBufferState,
                                         size,
                                         fIndexBufferState.fMinimumAlignment,
                                         binding);
    return VertexWriter{data, size};
}

void* StaticBufferManager::prepareStaticData(BufferState* state,
                                             size_t requiredBytes,
                                             size_t requiredAlignment,
                                             BindBufferInfo* target) {
    // Zero-out the target binding in the event of any failure in actually transfering data later.
    // Unlike in BufferSubAllocator::reserve(), we do use SkTo<uint32_t> to check
    // `requiredAlignment`. This is not dynamic data and is fully controlled by Graphite, so if it
    // asserts, then there is a bug in the static data for a Renderer that must be fixed.
    const uint32_t align32 = BufferAligner::LcmAlignment(state->fMinimumAlignment,
                                                         SkTo<uint32_t>(requiredAlignment));

    SkASSERT(target);
    *target = {nullptr, 0};
    uint32_t size32 = BufferAligner::ValidateCountAndStride(requiredBytes, /*stride=*/1,
                                                            /*headroom=*/0, align32);
    if (!size32 || fMappingFailed) {
        return nullptr;
    }

    // Copy data must be aligned to the transfer alignment, so align the reserved size to the LCM
    // of the minimum alignment (already net buffer and transfer alignment) and the required
    // alignment stride.
    size32 = SkAlignNonPow2(size32, align32);
    auto [transferMapPtr, transferBindInfo] =
            fUploadManager.makeBindInfo(size32,
                                        fRequiredTransferAlignment,
                                        "TransferForStaticBuffer");
    if (!transferMapPtr) {
        SKIA_LOG_E("Failed to create or map transfer buffer that initializes static GPU data.");
        fMappingFailed = true;
        return nullptr;
    }

    state->fData.push_back(
            {transferBindInfo,
             target,
             SkTo<uint32_t>(requiredAlignment),
#if defined(GPU_TEST_UTILS)
             SkTo<uint32_t>(requiredBytes)
#endif
            });

    state->fTotalRequiredBytes = SkAlignNonPow2(state->fTotalRequiredBytes, align32) + size32;

    return transferMapPtr;
}

bool StaticBufferManager::BufferState::createAndUpdateBindings(
        ResourceProvider* resourceProvider,
        Context* context,
        QueueManager* queueManager,
        GlobalCache* globalCache,
        std::string_view label) const {
    if (!fTotalRequiredBytes) {
        return true; // No buffer needed
    }

    // The static buffer is always copyable when testing.
    constexpr AccessPattern gpuAccessPattern =
#if defined(GPU_TEST_UTILS)
        AccessPattern::kGpuOnlyCopySrc;
#else
        AccessPattern::kGpuOnly;
#endif

    sk_sp<Buffer> staticBuffer = resourceProvider->findOrCreateNonShareableBuffer(
            fTotalRequiredBytes,
            fBufferType,
            gpuAccessPattern,
            label);
    if (!staticBuffer) {
        SKIA_LOG_E("Failed to create static buffer for type %d of size %u bytes.\n",
                    (int) fBufferType, fTotalRequiredBytes);
        return false;
    }

    uint32_t offset = 0;
    for (const CopyRange& data : fData) {
        // Each copy range's size should be aligned to the lcm of the required alignment and minimum
        // alignment so we can increment the offset in the static buffer.
        const uint32_t alignment = BufferAligner::LcmAlignment(fMinimumAlignment,
                                                               data.fRequiredAlignment);
        offset = SkAlignNonPow2(offset, alignment);
        SkASSERT(!(offset % fMinimumAlignment) && !(offset % data.fRequiredAlignment));
        uint32_t size = data.fSource.fSize;
        data.fTarget->fBuffer = staticBuffer.get();
        data.fTarget->fOffset = offset;
        data.fTarget->fSize = size;

        auto copyTask = CopyBufferToBufferTask::Make(
                data.fSource.fBuffer, data.fSource.fOffset,
                sk_ref_sp(data.fTarget->fBuffer), data.fTarget->fOffset,
                size);
        // For static buffers, we want them all to be optimized as GPU only buffers. If we are in
        // a protected context, this means the buffers must be non-protected since they will be
        // read in the vertex shader which doesn't allow protected memory access. Thus all the
        // uploads to these buffers must be done as non-protected commands.
        if (!queueManager->addTask(copyTask.get(), context, Protected::kNo)) {
            SKIA_LOG_E("Failed to copy data to static buffer.\n");
            return false;
        }

        offset += size;
    }

    SkASSERT(offset == fTotalRequiredBytes);
    globalCache->addStaticResource(std::move(staticBuffer));
    return true;
}

StaticBufferManager::FinishResult StaticBufferManager::finalize(Context* context,
                                                                QueueManager* queueManager,
                                                                GlobalCache* globalCache) {
    if (fMappingFailed) {
        return FinishResult::kFailure;
    }

    const size_t totalRequiredBytes = fVertexBufferState.fTotalRequiredBytes +
                                      fIndexBufferState.fTotalRequiredBytes;
    SkASSERT(totalRequiredBytes <= kMaxStaticDataSize);
    if (!totalRequiredBytes) {
        return FinishResult::kNoWork;
    }

    queueManager->addUploadBufferManagerRefs(&fUploadManager, context->priv().resourceProvider());

    if (!fVertexBufferState.createAndUpdateBindings(fResourceProvider,
                                                   context,
                                                   queueManager,
                                                   globalCache,
                                                   "StaticVertexBuffer")) {
        return FinishResult::kFailure;
    }

#if defined(GPU_TEST_UTILS)
    skia_private::TArray<GlobalCache::StaticVertexCopyRanges> statVertCopy;
    for (const CopyRange& data : fVertexBufferState.fData) {
        statVertCopy.push_back({data.fTarget->fOffset,
                                data.fUnalignedSize,
                                data.fTarget->fSize,
                                data.fRequiredAlignment});
    }
    globalCache->testingOnly_SetStaticVertexInfo(
            statVertCopy,
            fVertexBufferState.fData[0].fTarget->fBuffer);
#endif

    if (!fIndexBufferState.createAndUpdateBindings(fResourceProvider,
                                                   context,
                                                   queueManager,
                                                   globalCache,
                                                   "StaticIndexBuffer")) {
        return FinishResult::kFailure;
    }

    // Reset the static buffer manager since the Recording's copy tasks now manage ownership of
    // the transfer buffers and the GlobalCache owns the final static buffers.
    fVertexBufferState.reset();
    fIndexBufferState.reset();

    return FinishResult::kSuccess;
}

} // namespace skgpu::graphite
