Skip to content

Commit c1b5666

Browse files
authored
Merge pull request #276 from inexorgame/hanni/descriptor_builder
[descriptors] Apply builder pattern to shader resource descriptors
2 parents 5ffbff1 + 59b0e0d commit c1b5666

File tree

12 files changed

+208
-79
lines changed

12 files changed

+208
-79
lines changed

include/inexor/vulkan-renderer/imgui.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "inexor/vulkan-renderer/wrapper/command_buffer.hpp"
44
#include "inexor/vulkan-renderer/wrapper/command_pool.hpp"
5+
#include "inexor/vulkan-renderer/wrapper/descriptor.hpp"
56
#include "inexor/vulkan-renderer/wrapper/device.hpp"
67
#include "inexor/vulkan-renderer/wrapper/fence.hpp"
78
#include "inexor/vulkan-renderer/wrapper/framebuffer.hpp"
@@ -10,7 +11,6 @@
1011
#include "inexor/vulkan-renderer/wrapper/make_info.hpp"
1112
#include "inexor/vulkan-renderer/wrapper/mesh_buffer.hpp"
1213
#include "inexor/vulkan-renderer/wrapper/renderpass.hpp"
13-
#include "inexor/vulkan-renderer/wrapper/resource_descriptor.hpp"
1414
#include "inexor/vulkan-renderer/wrapper/shader.hpp"
1515
#include "inexor/vulkan-renderer/wrapper/swapchain.hpp"
1616

include/inexor/vulkan-renderer/renderer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "inexor/vulkan-renderer/time_step.hpp"
1313
#include "inexor/vulkan-renderer/wrapper/command_buffer.hpp"
1414
#include "inexor/vulkan-renderer/wrapper/command_pool.hpp"
15+
#include "inexor/vulkan-renderer/wrapper/descriptor.hpp"
1516
#include "inexor/vulkan-renderer/wrapper/device.hpp"
1617
#include "inexor/vulkan-renderer/wrapper/fence.hpp"
1718
#include "inexor/vulkan-renderer/wrapper/framebuffer.hpp"
@@ -20,7 +21,6 @@
2021
#include "inexor/vulkan-renderer/wrapper/image.hpp"
2122
#include "inexor/vulkan-renderer/wrapper/instance.hpp"
2223
#include "inexor/vulkan-renderer/wrapper/mesh_buffer.hpp"
23-
#include "inexor/vulkan-renderer/wrapper/resource_descriptor.hpp"
2424
#include "inexor/vulkan-renderer/wrapper/semaphore.hpp"
2525
#include "inexor/vulkan-renderer/wrapper/shader.hpp"
2626
#include "inexor/vulkan-renderer/wrapper/swapchain.hpp"

include/inexor/vulkan-renderer/wrapper/resource_descriptor.hpp renamed to include/inexor/vulkan-renderer/wrapper/descriptor.hpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,18 @@ class ResourceDescriptor {
1818
std::vector<VkDescriptorSetLayoutBinding> m_descriptor_set_layout_bindings;
1919
std::vector<VkWriteDescriptorSet> m_write_descriptor_sets;
2020
std::vector<VkDescriptorSet> m_descriptor_sets;
21-
std::uint32_t m_swapchain_image_count{};
21+
std::uint32_t m_swapchain_image_count;
2222

2323
public:
2424
/// @brief Default constructor.
2525
/// @param device The const reference to a device RAII wrapper instance.
2626
/// @param swapchain_image_count The number of images in swapchain.
27-
/// @param pool_types The descriptor pool types.
2827
/// @param layout_bindings The descriptor layout bindings.
2928
/// @param descriptor_writes The write descriptor sets.
3029
/// @param name The internal debug marker name of the resource descriptor.
3130
ResourceDescriptor(const Device &device, std::uint32_t swapchain_image_count,
32-
std::initializer_list<VkDescriptorType> pool_types,
33-
const std::vector<VkDescriptorSetLayoutBinding> &layout_bindings,
34-
const std::vector<VkWriteDescriptorSet> &descriptor_writes, const std::string &name);
31+
std::vector<VkDescriptorSetLayoutBinding> &&layout_bindings,
32+
std::vector<VkWriteDescriptorSet> &&descriptor_writes, std::string &&name);
3533

3634
ResourceDescriptor(const ResourceDescriptor &) = delete;
3735
ResourceDescriptor(ResourceDescriptor &&) noexcept;
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#pragma once
2+
3+
#include <vulkan/vulkan_core.h>
4+
5+
#include <cassert>
6+
#include <string>
7+
#include <vector>
8+
9+
namespace inexor::vulkan_renderer::wrapper {
10+
11+
// forward declarations
12+
class Device;
13+
class ResourceDescriptor;
14+
15+
class DescriptorBuilder {
16+
const Device &m_device;
17+
const std::uint32_t m_swapchain_image_count;
18+
19+
std::vector<VkDescriptorSetLayoutBinding> m_layout_bindings;
20+
std::vector<VkWriteDescriptorSet> m_write_sets;
21+
std::vector<VkDescriptorBufferInfo> m_descriptor_buffer_infos;
22+
std::vector<VkDescriptorImageInfo> m_descriptor_image_infos;
23+
24+
public:
25+
/// @brief Constructs the descriptor builder.
26+
/// @param device The const reference to a device RAII wrapper instance.
27+
/// @param swapchain_image_count The number of images in swapchain.
28+
DescriptorBuilder(const Device &device, std::uint32_t swapchain_image_count);
29+
30+
DescriptorBuilder(const DescriptorBuilder &) = delete;
31+
DescriptorBuilder(DescriptorBuilder &&) = delete;
32+
~DescriptorBuilder() = default;
33+
34+
DescriptorBuilder &operator=(const DescriptorBuilder &) = delete;
35+
DescriptorBuilder &operator=(DescriptorBuilder &&) = delete;
36+
37+
// TODO: Implement more descriptor types than just uniform buffers and combined image samplers.
38+
// TODO: Support uniform buffer offset in VkDescriptorBufferInfo.
39+
// TODO: Offer overloaded methods which expose more fields of the structures.
40+
41+
/// @brief Adds a uniform buffer to the descriptor container.
42+
/// @tparam T The type of the uniform buffer.
43+
/// @param uniform_buffer The uniform buffer which contains the data which will be accessed by the shader.
44+
/// @param binding The binding index which will be used in the SPIR-V shader.
45+
/// @param shader_stage The shader stage the uniform buffer will be used in, most likely the vertex shader.
46+
/// @return A const reference to this DescriptorBuilder instance.
47+
template <typename T>
48+
DescriptorBuilder &add_uniform_buffer(const VkBuffer uniform_buffer, const std::uint32_t binding,
49+
const VkShaderStageFlagBits shader_stage = VK_SHADER_STAGE_VERTEX_BIT);
50+
51+
/// @brief Adds a combined image sampler to the descriptor container.
52+
/// @param image_sampler The pointer to the combined image sampler.
53+
/// @param image_view The pointer to the image view.
54+
/// @param binding The binding index which will be used in the SPIR-V shader.
55+
/// @param shader_stage The shader stage the uniform buffer will be used in, most likely the fragment shader.
56+
/// @return A const reference to this DescriptorBuilder instance.
57+
DescriptorBuilder &
58+
add_combined_image_sampler(const VkSampler image_sampler, const VkImageView image_view, const std::uint32_t binding,
59+
const VkShaderStageFlagBits shader_stage = VK_SHADER_STAGE_FRAGMENT_BIT);
60+
61+
/// @brief Builds the resource descriptor.
62+
/// @param name The internal name of the resource descriptor.
63+
/// @return The resource descriptor which was created by the builder.
64+
[[nodiscard]] ResourceDescriptor build(std::string name);
65+
};
66+
67+
template <typename T>
68+
DescriptorBuilder &DescriptorBuilder::add_uniform_buffer(const VkBuffer uniform_buffer, const std::uint32_t binding,
69+
const VkShaderStageFlagBits shader_stage) {
70+
assert(uniform_buffer);
71+
72+
VkDescriptorSetLayoutBinding layout_binding{};
73+
layout_binding.binding = binding;
74+
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
75+
layout_binding.descriptorCount = 1;
76+
layout_binding.stageFlags = shader_stage;
77+
layout_binding.pImmutableSamplers = nullptr;
78+
79+
m_layout_bindings.push_back(layout_binding);
80+
81+
VkDescriptorBufferInfo uniform_buffer_info{};
82+
uniform_buffer_info.buffer = uniform_buffer;
83+
uniform_buffer_info.offset = 0;
84+
uniform_buffer_info.range = sizeof(T);
85+
86+
m_descriptor_buffer_infos.push_back(uniform_buffer_info);
87+
88+
VkWriteDescriptorSet descriptor_write{};
89+
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
90+
descriptor_write.dstSet = nullptr;
91+
descriptor_write.dstBinding = binding;
92+
descriptor_write.dstArrayElement = 0;
93+
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
94+
descriptor_write.descriptorCount = 1;
95+
descriptor_write.pBufferInfo = &m_descriptor_buffer_infos.back();
96+
97+
m_write_sets.push_back(descriptor_write);
98+
99+
return *this;
100+
}
101+
102+
} // namespace inexor::vulkan_renderer::wrapper

include/inexor/vulkan-renderer/wrapper/uniform_buffer.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ class Device;
1212

1313
/// @brief RAII wrapper class for uniform buffers.
1414
class UniformBuffer : public GPUMemoryBuffer {
15-
protected:
16-
VkDescriptorBufferInfo m_descriptor_buffer_info{};
17-
VkDescriptorSet m_descriptor_set{};
18-
1915
public:
2016
/// @brief Default constructor.
2117
/// @param device The const reference to a device RAII wrapper instance.

src/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ set(INEXOR_SOURCE_FILES
2121
vulkan-renderer/wrapper/command_buffer.cpp
2222
vulkan-renderer/wrapper/command_pool.cpp
2323
vulkan-renderer/wrapper/cpu_texture.cpp
24+
vulkan-renderer/wrapper/descriptor.cpp
25+
vulkan-renderer/wrapper/descriptor_builder.cpp
2426
vulkan-renderer/wrapper/device.cpp
2527
vulkan-renderer/wrapper/fence.cpp
2628
vulkan-renderer/wrapper/framebuffer.cpp
@@ -33,7 +35,6 @@ set(INEXOR_SOURCE_FILES
3335
vulkan-renderer/wrapper/make_info.cpp
3436
vulkan-renderer/wrapper/once_command_buffer.cpp
3537
vulkan-renderer/wrapper/renderpass.cpp
36-
vulkan-renderer/wrapper/resource_descriptor.cpp
3738
vulkan-renderer/wrapper/semaphore.cpp
3839
vulkan-renderer/wrapper/shader.cpp
3940
vulkan-renderer/wrapper/staging_buffer.cpp

src/vulkan-renderer/application.cpp

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "inexor/vulkan-renderer/tools/cla_parser.hpp"
77
#include "inexor/vulkan-renderer/world/cube.hpp"
88
#include "inexor/vulkan-renderer/wrapper/cpu_texture.hpp"
9+
#include "inexor/vulkan-renderer/wrapper/descriptor_builder.hpp"
910
#include "inexor/vulkan-renderer/wrapper/make_info.hpp"
1011

1112
#include <glm/gtc/matrix_transform.hpp>
@@ -384,37 +385,14 @@ Application::Application(int argc, char **argv) {
384385

385386
m_uniform_buffers.emplace_back(*m_device, "matrices uniform buffer", sizeof(UniformBufferObject));
386387

387-
std::vector<VkDescriptorSetLayoutBinding> layout_bindings(1);
388-
389-
layout_bindings[0].binding = 0;
390-
layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
391-
layout_bindings[0].descriptorCount = 1;
392-
layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
393-
layout_bindings[0].pImmutableSamplers = nullptr;
394-
395-
std::vector<VkWriteDescriptorSet> descriptor_writes(1);
396-
397-
// Link the matrices uniform buffer to the descriptor set so the shader can access it.
398-
399-
// We can do better than this, but therefore RAII refactoring needs to be done..
400-
m_uniform_buffer_info.buffer = m_uniform_buffers[0].buffer();
401-
m_uniform_buffer_info.offset = 0;
402-
m_uniform_buffer_info.range = sizeof(UniformBufferObject);
403-
404-
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
405-
descriptor_writes[0].dstSet = nullptr;
406-
descriptor_writes[0].dstBinding = 0;
407-
descriptor_writes[0].dstArrayElement = 0;
408-
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
409-
descriptor_writes[0].descriptorCount = 1;
410-
descriptor_writes[0].pBufferInfo = &m_uniform_buffer_info;
411-
412-
m_descriptors.emplace_back(wrapper::ResourceDescriptor{*m_device,
413-
m_swapchain->image_count(),
414-
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER},
415-
layout_bindings,
416-
descriptor_writes,
417-
"Default descriptor"});
388+
// Create an instance of the resource descriptor builder.
389+
// This allows us to make resource descriptors with the help of a builder pattern.
390+
wrapper::DescriptorBuilder descriptor_builder(*m_device, m_swapchain->image_count());
391+
392+
// Make use of the builder to create a resource descriptor for the uniform buffer.
393+
m_descriptors.emplace_back(
394+
descriptor_builder.add_uniform_buffer<UniformBufferObject>(m_uniform_buffers[0].buffer(), 0)
395+
.build("Default uniform buffer"));
418396

419397
load_octree_geometry();
420398
generate_octree_indices();

src/vulkan-renderer/imgui.cpp

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "inexor/vulkan-renderer/imgui.hpp"
22

33
#include "inexor/vulkan-renderer/wrapper/cpu_texture.hpp"
4+
#include "inexor/vulkan-renderer/wrapper/descriptor_builder.hpp"
45
#include "inexor/vulkan-renderer/wrapper/make_info.hpp"
56

67
#include <cassert>
@@ -116,30 +117,14 @@ ImGUIOverlay::ImGUIOverlay(const wrapper::Device &device, const wrapper::Swapcha
116117

117118
m_command_pool = std::make_unique<wrapper::CommandPool>(m_device, m_device.graphics_queue_family_index());
118119

119-
VkDescriptorImageInfo font_desc{};
120-
font_desc.sampler = m_imgui_texture->sampler();
121-
font_desc.imageView = m_imgui_texture->image_view();
122-
font_desc.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
123-
124-
std::vector<VkDescriptorSetLayoutBinding> layout_bindings(1);
125-
layout_bindings[0].binding = 0;
126-
layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
127-
layout_bindings[0].descriptorCount = 1;
128-
layout_bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
129-
130-
std::vector<VkWriteDescriptorSet> desc_writes(1);
131-
desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
132-
desc_writes[0].dstSet = nullptr;
133-
desc_writes[0].dstBinding = 0;
134-
desc_writes[0].dstArrayElement = 0;
135-
desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
136-
desc_writes[0].descriptorCount = 1;
137-
desc_writes[0].pImageInfo = &font_desc;
138-
139-
std::initializer_list<VkDescriptorType> pool_types = {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER};
140-
141-
m_descriptor = std::make_unique<wrapper::ResourceDescriptor>(m_device, swapchain.image_count(), pool_types,
142-
layout_bindings, desc_writes, "ImGUI");
120+
// Create an instance of the resource descriptor builder.
121+
// This allows us to make resource descriptors with the help of a builder pattern.
122+
wrapper::DescriptorBuilder descriptor_builder(m_device, m_swapchain.image_count());
123+
124+
// Make use of the builder to create a resource descriptor for the combined image sampler.
125+
m_descriptor = std::make_unique<wrapper::ResourceDescriptor>(
126+
descriptor_builder.add_combined_image_sampler(m_imgui_texture->sampler(), m_imgui_texture->image_view(), 0)
127+
.build("ImGUI"));
143128

144129
// TODO() Use pipeline cache!
145130
std::vector<VkAttachmentDescription> attachments(1);

src/vulkan-renderer/wrapper/command_buffer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#include "inexor/vulkan-renderer/wrapper/command_buffer.hpp"
22

3+
#include "inexor/vulkan-renderer/wrapper/descriptor.hpp"
34
#include "inexor/vulkan-renderer/wrapper/device.hpp"
45
#include "inexor/vulkan-renderer/wrapper/make_info.hpp"
5-
#include "inexor/vulkan-renderer/wrapper/resource_descriptor.hpp"
66

77
#include <array>
88
#include <cassert>

src/vulkan-renderer/wrapper/resource_descriptor.cpp renamed to src/vulkan-renderer/wrapper/descriptor.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "inexor/vulkan-renderer/wrapper/resource_descriptor.hpp"
1+
#include "inexor/vulkan-renderer/wrapper/descriptor.hpp"
22

33
#include "inexor/vulkan-renderer/wrapper/device.hpp"
44
#include "inexor/vulkan-renderer/wrapper/make_info.hpp"
@@ -18,10 +18,8 @@ ResourceDescriptor::ResourceDescriptor(ResourceDescriptor &&other) noexcept
1818
m_descriptor_sets(std::move(other.m_descriptor_sets)), m_swapchain_image_count(other.m_swapchain_image_count) {}
1919

2020
ResourceDescriptor::ResourceDescriptor(const Device &device, std::uint32_t swapchain_image_count,
21-
std::initializer_list<VkDescriptorType> pool_types,
22-
const std::vector<VkDescriptorSetLayoutBinding> &layout_bindings,
23-
const std::vector<VkWriteDescriptorSet> &descriptor_writes,
24-
const std::string &name)
21+
std::vector<VkDescriptorSetLayoutBinding> &&layout_bindings,
22+
std::vector<VkWriteDescriptorSet> &&descriptor_writes, std::string &&name)
2523
: m_device(device), m_name(name), m_write_descriptor_sets(descriptor_writes),
2624
m_descriptor_set_layout_bindings(layout_bindings), m_swapchain_image_count(swapchain_image_count) {
2725
assert(device.device());
@@ -30,12 +28,17 @@ ResourceDescriptor::ResourceDescriptor(const Device &device, std::uint32_t swapc
3028
assert(!m_write_descriptor_sets.empty());
3129
assert(layout_bindings.size() == m_write_descriptor_sets.size());
3230

33-
// TODO() Check if descriptor writes match descriptor set layout!
31+
for (std::size_t i = 0; i < layout_bindings.size(); i++) {
32+
if (layout_bindings[i].descriptorType != descriptor_writes[i].descriptorType) {
33+
throw std::runtime_error(
34+
"VkDescriptorType mismatch in descriptor set layout binding and write descriptor set!");
35+
}
36+
}
3437

3538
std::vector<VkDescriptorPoolSize> pool_sizes;
3639

37-
for (const auto &descriptor_pool_type : pool_types) {
38-
pool_sizes.emplace_back(VkDescriptorPoolSize{descriptor_pool_type, swapchain_image_count});
40+
for (const auto &descriptor_pool_type : layout_bindings) {
41+
pool_sizes.emplace_back(VkDescriptorPoolSize{descriptor_pool_type.descriptorType, swapchain_image_count});
3942
}
4043

4144
spdlog::debug("Creating new descriptor pool.");

0 commit comments

Comments
 (0)