/*
 * Copyright 2023 Rive
 */

#include "rive/renderer/vulkan/vkutil.hpp"

#include "rive/rive_types.hpp"
#include "rive/renderer/vulkan/vulkan_context.hpp"

namespace rive::gpu::vkutil
{
void vkutil::RenderingResource::onRefCntReachedZero() const
{
    // VulkanContext will hold off on deleting "this" until any in-flight
    // command buffers have finished (potentially) referencing our underlying
    // Vulkan objects.
    m_vk->onRenderingResourceReleased(this);
}

Buffer::Buffer(rcp<VulkanContext> vk,
               const VkBufferCreateInfo& info,
               Mappability mappability) :
    RenderingResource(std::move(vk)), m_mappability(mappability), m_info(info)
{
    m_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    init();
}

Buffer::~Buffer() { resizeImmediately(0); }

void Buffer::resizeImmediately(size_t sizeInBytes)
{
    if (m_info.size != sizeInBytes)
    {
        if (m_vmaAllocation != VK_NULL_HANDLE)
        {
            if (m_mappability != Mappability::none)
            {
                vmaUnmapMemory(m_vk->vmaAllocator, m_vmaAllocation);
            }
            vmaDestroyBuffer(m_vk->vmaAllocator, m_vkBuffer, m_vmaAllocation);
        }
        m_info.size = sizeInBytes;
        init();
    }
}

VmaAllocationCreateFlags vma_flags_for_mappability(Mappability mappability)
{
    switch (mappability)
    {
        case Mappability::none:
            return 0;
        case Mappability::writeOnly:
            return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
        case Mappability::readWrite:
            return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
    }
    RIVE_UNREACHABLE();
}

void Buffer::init()
{
    if (m_info.size > 0)
    {
        VmaAllocationCreateInfo allocInfo = {
            .flags = vma_flags_for_mappability(m_mappability),
            .usage = VMA_MEMORY_USAGE_AUTO,
        };

        VK_CHECK(vmaCreateBuffer(m_vk->vmaAllocator,
                                 &m_info,
                                 &allocInfo,
                                 &m_vkBuffer,
                                 &m_vmaAllocation,
                                 nullptr));

        if (m_mappability != Mappability::none)
        {
            // Leave the buffer constantly mapped and let the OS/drivers handle
            // the rest.
            VK_CHECK(
                vmaMapMemory(m_vk->vmaAllocator, m_vmaAllocation, &m_contents));
        }
        else
        {
            m_contents = nullptr;
        }
    }
    else
    {
        m_vkBuffer = VK_NULL_HANDLE;
        m_vmaAllocation = VK_NULL_HANDLE;
        m_contents = nullptr;
    }
}

void Buffer::flushContents(size_t updatedSizeInBytes)
{
    // Leave the buffer constantly mapped and let the OS/drivers handle the
    // rest.
    vmaFlushAllocation(m_vk->vmaAllocator,
                       m_vmaAllocation,
                       0,
                       updatedSizeInBytes);
}

void Buffer::invalidateContents(size_t updatedSizeInBytes)
{
    vmaInvalidateAllocation(m_vk->vmaAllocator,
                            m_vmaAllocation,
                            0,
                            updatedSizeInBytes);
}

BufferRing::BufferRing(rcp<VulkanContext> vk,
                       VkBufferUsageFlags usage,
                       Mappability mappability,
                       size_t size) :
    m_targetSize(size)
{
    VkBufferCreateInfo bufferCreateInfo = {
        .size = size,
        .usage = usage,
    };
    for (int i = 0; i < gpu::kBufferRingSize; ++i)
    {
        m_buffers[i] = vk->makeBuffer(bufferCreateInfo, mappability);
    }
}

void BufferRing::setTargetSize(size_t size)
{
    // Buffers always get bound, even if unused, so make sure they aren't empty
    // and we get a valid Vulkan handle.
    if (m_buffers[0]->info().usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
    {
        size = std::max<size_t>(size, 256);
        // Uniform blocks must be multiples of 256 bytes in size.
        assert(size % 256 == 0);
    }
    else
    {
        size = std::max<size_t>(size, 1);
    }
    m_targetSize = size;
}

void BufferRing::synchronizeSizeAt(int bufferRingIdx)
{
    if (m_buffers[bufferRingIdx]->info().size != m_targetSize)
    {
        m_buffers[bufferRingIdx]->resizeImmediately(m_targetSize);
    }
}

void* BufferRing::contentsAt(int bufferRingIdx, size_t dirtySize)
{
    m_pendingFlushSize = dirtySize;
    return m_buffers[bufferRingIdx]->contents();
}

void BufferRing::flushContentsAt(int bufferRingIdx)
{
    assert(m_pendingFlushSize > 0);
    m_buffers[bufferRingIdx]->flushContents(m_pendingFlushSize);
    m_pendingFlushSize = 0;
}

Texture::Texture(rcp<VulkanContext> vk, const VkImageCreateInfo& info) :
    RenderingResource(std::move(vk)), m_info(info)
{
    m_info = info;
    m_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;

    if (m_info.imageType == 0)
    {
        m_info.imageType = VK_IMAGE_TYPE_2D;
    }

    if (m_info.mipLevels == 0)
    {
        m_info.mipLevels = 1;
    }
    else if (m_info.mipLevels > 1)
    {
        // We generate mipmaps internally with image blits.
        m_info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
    }

    if (m_info.arrayLayers == 0)
    {
        m_info.arrayLayers = 1;
    }

    if (m_info.samples == 0)
    {
        m_info.samples = VK_SAMPLE_COUNT_1_BIT;
    }

    if (m_info.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT)
    {
        // Attempt to create transient attachments with lazily-allocated memory.
        // This should succeed on mobile. Otherwise, use normal memory.
        VmaAllocationCreateInfo allocInfo = {
            .usage = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED,
        };

        if (vmaCreateImage(m_vk->vmaAllocator,
                           &m_info,
                           &allocInfo,
                           &m_vkImage,
                           &m_vmaAllocation,
                           nullptr) == VK_SUCCESS)
        {
            return;
        }
    }

    VmaAllocationCreateInfo allocInfo = {
        .usage = VMA_MEMORY_USAGE_AUTO,
    };

    VK_CHECK(vmaCreateImage(m_vk->vmaAllocator,
                            &m_info,
                            &allocInfo,
                            &m_vkImage,
                            &m_vmaAllocation,
                            nullptr));
}

Texture::~Texture()
{
    if (m_vmaAllocation != VK_NULL_HANDLE)
    {
        vmaDestroyImage(m_vk->vmaAllocator, m_vkImage, m_vmaAllocation);
    }
}

TextureView::TextureView(rcp<VulkanContext> vk,
                         rcp<Texture> textureRef,
                         VkImageUsageFlags flags,
                         const VkImageViewCreateInfo& info) :
    RenderingResource(std::move(vk)),
    m_textureRefOrNull(std::move(textureRef)),
    m_usageFlags(flags),
    m_info(info)
{
    m_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
    VK_CHECK(
        m_vk->CreateImageView(m_vk->device, &m_info, nullptr, &m_vkImageView));
}

TextureView::~TextureView()
{
    m_vk->DestroyImageView(m_vk->device, m_vkImageView, nullptr);
}

Framebuffer::Framebuffer(rcp<VulkanContext> vk,
                         const VkFramebufferCreateInfo& info) :
    RenderingResource(std::move(vk)), m_info(info)
{
    m_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    VK_CHECK(m_vk->CreateFramebuffer(m_vk->device,
                                     &m_info,
                                     nullptr,
                                     &m_vkFramebuffer));
}

Framebuffer::~Framebuffer()
{
    m_vk->DestroyFramebuffer(m_vk->device, m_vkFramebuffer, nullptr);
}
} // namespace rive::gpu::vkutil
