/*
 * Copyright 2023 Rive
 */

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

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

namespace rive::pls::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)
        {
            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));

        // 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_vkBuffer = VK_NULL_HANDLE;
        m_vmaAllocation = VK_NULL_HANDLE;
        m_contents = nullptr;
    }
}

void Buffer::flushMappedContents(size_t updatedSizeInBytes)
{
    // Leave the buffer constantly mapped and let the OS/drivers handle the
    // rest.
    vmaFlushAllocation(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 < pls::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::flushMappedContentsAt(int bufferRingIdx)
{
    assert(m_pendingFlushSize > 0);
    m_buffers[bufferRingIdx]->flushMappedContents(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)
        {
            printf("SUCCESS AT TRANSIENT LAZY!\n");
            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::pls::vkutil
