/*
	VulkanFramework
	by John Ryland
	Copyright (c) 2023
*/

////////////////////////////////////////////////////////////////////////////////////
//	Vulkan Command Pool

#include "VulkanCommandPool.h"

namespace Vulkan {

CommandPool::CommandPool()
    : m_owner(nullptr)
{
}

// virtual
void CommandPool::Initialize(Device* device)
{
    m_owner = device;
    VkCommandPoolCreateInfo poolInfo {};
    poolInfo.sType            = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    poolInfo.flags            = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
    poolInfo.queueFamilyIndex = m_owner->m_graphicsQueueFamily;
    m_owner->CheckResult(vkCreateCommandPool(m_owner->m_device, &poolInfo, m_owner->m_allocator, &m_commandPool), "failed to create graphics command pool!");
}

// virtual
CommandPool::~CommandPool()
{
    Destroy();
}

// virtual
void CommandPool::Destroy()
{
    vkDestroyCommandPool(m_owner->m_device, m_commandPool, nullptr);
}

VkCommandBuffer CommandPool::BeginSingleTimeCommands()
{
    VkCommandBufferAllocateInfo allocInfo {};
    allocInfo.sType              = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    allocInfo.level              = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    allocInfo.commandPool        = m_commandPool;
    allocInfo.commandBufferCount = 1;

    VkCommandBuffer commandBuffer;
    vkAllocateCommandBuffers(m_owner->m_device, &allocInfo, &commandBuffer);

    VkCommandBufferBeginInfo beginInfo {};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;

    vkBeginCommandBuffer(commandBuffer, &beginInfo);

    return commandBuffer;
}

void CommandPool::EndSingleTimeCommands(VkCommandBuffer commandBuffer)
{
    vkEndCommandBuffer(commandBuffer);

    VkSubmitInfo submitInfo {};
    submitInfo.sType              = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.commandBufferCount = 1;
    submitInfo.pCommandBuffers    = &commandBuffer;

    vkQueueSubmit(m_owner->m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
    vkQueueWaitIdle(m_owner->m_graphicsQueue);

    vkFreeCommandBuffers(m_owner->m_device, m_commandPool, 1, &commandBuffer);
}

} // Vulkan namespace
