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

#include "include/gpu/graphite/Recording.h"
#include "include/private/SkAlign.h"
#include "include/private/SkTFitsIn.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/CommandBuffer.h"
#include "src/gpu/graphite/RecordingPriv.h"
#include "src/gpu/graphite/ResourceProvider.h"

namespace skgpu::graphite {

static constexpr size_t kReusedBufferSize = 64 << 10;  // 64 KB

UploadBufferManager::UploadBufferManager(ResourceProvider* resourceProvider,
                                         const Caps* caps)
        : fResourceProvider(resourceProvider)
        , fMinAlignment(SkTo<uint32_t>(caps->requiredTransferBufferAlignment())) {}

UploadBufferManager::~UploadBufferManager() {}

std::tuple<TextureUploadWriter, BindBufferInfo> UploadBufferManager::getTextureUploadWriter(
        size_t requiredBytes, size_t requiredAlignment) {
    auto[bufferMapPtr, bindInfo] = this->makeBindInfo(requiredBytes,
                                                      requiredAlignment,
                                                      "TextureUploadBuffer");
    if (!bufferMapPtr) {
        return {TextureUploadWriter(), BindBufferInfo()};
    }

    return {TextureUploadWriter(bufferMapPtr, requiredBytes), bindInfo};
}

std::tuple<void* /*mappedPtr*/, BindBufferInfo> UploadBufferManager::makeBindInfo(
        size_t requiredBytes, size_t requiredAlignment, std::string_view label) {
    if (!SkTFitsIn<uint32_t>(requiredBytes)) {
        return {nullptr, BindBufferInfo()};
    }

    uint32_t requiredAlignment32 = std::max(SkTo<uint32_t>(requiredAlignment), fMinAlignment);
    uint32_t requiredBytes32 = SkAlignNonPow2(SkTo<uint32_t>(requiredBytes), requiredAlignment32);
    if (requiredBytes32 > kReusedBufferSize) {
        // Create a dedicated buffer for this request.
        sk_sp<Buffer> buffer = fResourceProvider->findOrCreateNonShareableBuffer(
                requiredBytes32,
                BufferType::kXferCpuToGpu,
                AccessPattern::kHostVisible,
                label);
        void* bufferMapPtr = buffer ? buffer->map() : nullptr;
        if (!bufferMapPtr) {
            // Unlike [Draw|Static]BufferManager, the UploadManager does not track if any buffer
            // mapping has failed. This is because it's common for uploads to be scoped to a
            // specific image creation. In that case, the image can be returned as null to signal a
            // very isolated failure instead of taking down the entire Recording. For the other
            // managers, failures to map buffers creates unrecoverable scenarios.
            return {nullptr, BindBufferInfo()};
        }

        BindBufferInfo bindInfo;
        bindInfo.fBuffer = buffer.get();
        bindInfo.fOffset = 0;
        bindInfo.fSize = requiredBytes32;

        fUsedBuffers.push_back(std::move(buffer));
        return {bufferMapPtr, bindInfo};
    }

    // Try to reuse an already-allocated buffer.
    fReusedBufferOffset = SkAlignNonPow2(fReusedBufferOffset, requiredAlignment32);
    if (fReusedBuffer && requiredBytes32 > fReusedBuffer->size() - fReusedBufferOffset) {
        fUsedBuffers.push_back(std::move(fReusedBuffer));
    }

    if (!fReusedBuffer) {
        fReusedBuffer = fResourceProvider->findOrCreateNonShareableBuffer(
                kReusedBufferSize,
                BufferType::kXferCpuToGpu,
                AccessPattern::kHostVisible,
                label);
        fReusedBufferOffset = 0;
        if (!fReusedBuffer || !fReusedBuffer->map()) {
            fReusedBuffer = nullptr;
            return {nullptr, BindBufferInfo()};
        }
    }

    BindBufferInfo bindInfo;
    bindInfo.fBuffer = fReusedBuffer.get();
    bindInfo.fOffset = fReusedBufferOffset;
    bindInfo.fSize = requiredBytes32;

    void* bufferMapPtr = fReusedBuffer->map();
    SkASSERT(bufferMapPtr); // Should have been validated when it was created
    bufferMapPtr = SkTAddOffset<void>(bufferMapPtr, fReusedBufferOffset);

    fReusedBufferOffset += requiredBytes32;

    return {bufferMapPtr, bindInfo};
}

void UploadBufferManager::transferToRecording(Recording* recording) {
    for (sk_sp<Buffer>& buffer : fUsedBuffers) {
        buffer->unmap();
        recording->priv().addResourceRef(std::move(buffer));
    }
    fUsedBuffers.clear();

    if (fReusedBuffer) {
        fReusedBuffer->unmap();
        recording->priv().addResourceRef(std::move(fReusedBuffer));
    }
}

void UploadBufferManager::transferToCommandBuffer(CommandBuffer* commandBuffer) {
    for (sk_sp<Buffer>& buffer : fUsedBuffers) {
        buffer->unmap();
        commandBuffer->trackResource(std::move(buffer));
    }
    fUsedBuffers.clear();

    if (fReusedBuffer) {
        fReusedBuffer->unmap();
        commandBuffer->trackResource(std::move(fReusedBuffer));
    }
}

}  // namespace skgpu::graphite
