/*
 * Copyright 2025 Rive
 */

#include "rive/renderer/gpu_resource.hpp"

namespace rive::gpu
{
GPUResource::~GPUResource() {}

void GPUResource::onRefCntReachedZero() const
{
    // GPUResourceManager will hold off on deleting "this" until its safe frame
    // number has been reached.
    if (m_manager)
        m_manager->onRenderingResourceReleased(const_cast<GPUResource*>(this));
}

GPUResourceManager::~GPUResourceManager()
{
    // Call shutdown() before destroying the resource manager.
    assert(m_currentFrameNumber == SHUTDOWN_FRAME_NUMBER);
    assert(m_safeFrameNumber == SHUTDOWN_FRAME_NUMBER);
    assert(m_resourcePurgatory.empty());
}

void GPUResourceManager::advanceFrameNumber(uint64_t nextFrameNumber,
                                            uint64_t safeFrameNumber)
{
    assert(nextFrameNumber >= m_currentFrameNumber);
    assert(safeFrameNumber >= m_safeFrameNumber);
    assert(safeFrameNumber <= nextFrameNumber);

    m_currentFrameNumber = nextFrameNumber;
    m_safeFrameNumber = safeFrameNumber;

    // Delete all resources whose safe frame number has been reached.
    while (!m_resourcePurgatory.empty() &&
           m_resourcePurgatory.front().lastFrameNumber <= m_safeFrameNumber)
    {
        assert(m_resourcePurgatory.front().resource->debugging_refcnt() == 0);
        m_resourcePurgatory.pop_front();
    }
}

void GPUResourceManager::onRenderingResourceReleased(GPUResource* resource)
{
    assert(resource->manager() == this);
    if (m_currentFrameNumber > m_safeFrameNumber)
    {
        // Hold this resource until its safe frame number is reached.
        assert(resource->debugging_refcnt() == 0);
        assert(m_resourcePurgatory.empty() ||
               m_currentFrameNumber >=
                   m_resourcePurgatory.back().lastFrameNumber);
        m_resourcePurgatory.emplace_back(resource, m_currentFrameNumber);
    }
    else
    {
        // We're in a shutdown cycle. Delete immediately.
        delete resource;
    }
}

void GPUResourceManager::shutdown()
{
    advanceFrameNumber(SHUTDOWN_FRAME_NUMBER, SHUTDOWN_FRAME_NUMBER);
}

rcp<GPUResource> GPUResourcePool::acquire()
{
    rcp<GPUResource> resource;
    if (!m_pool.empty() &&
        m_pool.front().lastFrameNumber <= m_manager->safeFrameNumber())
    {
        // Recycle the oldest buffer in the pool.
        resource = rcp(m_pool.front().resource.release());
        m_pool.pop_front();

        // Trim the pool in case it's grown out of control (meaning it was
        // advanced multiple times in a single frame).
        while (m_pool.size() > m_maxPoolCount &&
               m_pool.front().lastFrameNumber <= m_manager->safeFrameNumber())
        {
            m_pool.pop_front();
        }
    }
    assert(resource == nullptr || resource->debugging_refcnt() == 1);
    return resource;
}

void GPUResourcePool::recycle(rcp<GPUResource> resource)
{
    if (resource != nullptr)
    {
        // Return the current buffer to the pool.
        assert(resource->debugging_refcnt() == 1);
        assert(m_pool.empty() || m_manager->currentFrameNumber() >=
                                     m_pool.back().lastFrameNumber);
        m_pool.emplace_back(resource.release(),
                            m_manager->currentFrameNumber());
    }
}
} // namespace rive::gpu
