Program Listing for File descriptor_builder.hpp

Return to documentation for file (inexor/vulkan-renderer/wrapper/descriptor_builder.hpp)

#pragma once

#include "inexor/vulkan-renderer/wrapper/make_info.hpp"

#include <volk.h>

#include <cassert>
#include <cstdint>
#include <string>
#include <vector>

namespace inexor::vulkan_renderer::wrapper {

// Forward declarations
class Device;
class ResourceDescriptor;

class DescriptorBuilder {
    const Device &m_device;

    std::vector<VkDescriptorSetLayoutBinding> m_layout_bindings;
    std::vector<VkWriteDescriptorSet> m_write_sets;
    std::vector<VkDescriptorBufferInfo> m_descriptor_buffer_infos;
    std::vector<VkDescriptorImageInfo> m_descriptor_image_infos;

public:
    explicit DescriptorBuilder(const Device &device);

    DescriptorBuilder(const DescriptorBuilder &) = delete;
    DescriptorBuilder(DescriptorBuilder &&) = delete;
    ~DescriptorBuilder() = default;

    DescriptorBuilder &operator=(const DescriptorBuilder &) = delete;
    DescriptorBuilder &operator=(DescriptorBuilder &&) = delete;

    // TODO: Implement more descriptor types than just uniform buffers and combined image samplers.
    // TODO: Support uniform buffer offset in VkDescriptorBufferInfo.
    // TODO: Offer overloaded methods which expose more fields of the structures.

    template <typename T>
    DescriptorBuilder &add_uniform_buffer(VkBuffer uniform_buffer, std::uint32_t binding,
                                          VkShaderStageFlagBits shader_stage = VK_SHADER_STAGE_VERTEX_BIT);

    DescriptorBuilder &add_combined_image_sampler(VkSampler image_sampler, VkImageView image_view,
                                                  std::uint32_t binding,
                                                  VkShaderStageFlagBits shader_stage = VK_SHADER_STAGE_FRAGMENT_BIT);

    [[nodiscard]] ResourceDescriptor build(std::string name);
};

template <typename T>
DescriptorBuilder &DescriptorBuilder::add_uniform_buffer(const VkBuffer uniform_buffer, const std::uint32_t binding,
                                                         const VkShaderStageFlagBits shader_stage) {
    assert(uniform_buffer);

    m_layout_bindings.push_back({
        .binding = binding,
        .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
        .descriptorCount = 1,
        .stageFlags = static_cast<VkShaderStageFlags>(shader_stage),
        .pImmutableSamplers = nullptr,
    });

    m_descriptor_buffer_infos.push_back({
        .buffer = uniform_buffer,
        .offset = 0,
        .range = sizeof(T),
    });

    m_write_sets.push_back(make_info<VkWriteDescriptorSet>({
        .dstSet = nullptr,
        .dstBinding = binding,
        .dstArrayElement = 0,
        .descriptorCount = 1,
        .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
        .pBufferInfo = &m_descriptor_buffer_infos.back(),
    }));

    return *this;
}

} // namespace inexor::vulkan_renderer::wrapper