#include <Vk/DescriptorSetLayout/DescriptorSetLayout.hpp>
#include <Utilities/Utilities.hpp>

Vk::DescriptorSetLayout::Builder& Vk::DescriptorSetLayout::Builder::addBinding(
    uint32_t binding, VkDescriptorType type, uint32_t count, VkShaderStageFlags stages
)
{
    VkDescriptorSetLayoutBinding layoutBinding{};
    layoutBinding.binding = binding;
    layoutBinding.descriptorType = type;
    layoutBinding.descriptorCount = count;
    layoutBinding.stageFlags = stages;

    m_bindings.push_back(layoutBinding);
    return *this;
}

std::shared_ptr<Vk::DescriptorSetLayout> Vk::DescriptorSetLayout::Builder::build(std::shared_ptr<Vk::Device> device)
{
    VkDescriptorSetLayoutCreateInfo layoutInfo{};
    layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    layoutInfo.bindingCount = m_bindings.size();
    layoutInfo.pBindings = m_bindings.data();

    VkDescriptorSetLayout layout;
    if (vkCreateDescriptorSetLayout(device->inner(), &layoutInfo, nullptr, &layout) != VK_SUCCESS)
    {
        crash("Failed to create descriptor set layout!");
    }

    std::shared_ptr<Vk::DescriptorSetLayout> result = std::make_shared<Vk::DescriptorSetLayout>();
    result->m_device = device;
    result->m_layout = layout;
    return result;
}

Vk::DescriptorSetLayout::~DescriptorSetLayout()
{
    vkDestroyDescriptorSetLayout(m_device->inner(), m_layout, nullptr);
}

VkDescriptorSetLayout Vk::DescriptorSetLayout::inner()
{
    return m_layout;
}