Skip to content

Commit

Permalink
[WIP] Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
IAmNotHanni committed Jul 13, 2024
1 parent 8832357 commit 669c13e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 40 deletions.
29 changes: 24 additions & 5 deletions include/inexor/vulkan-renderer/render-graph/render_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <functional>
#include <memory>
#include <optional>
#include <tuple>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -96,11 +97,7 @@ class RenderGraph {
// PIPELINES
// ---------------------------------------------------------------------------------------------------------
/// The callables which create the graphics pipelines used in the rendergraph
using GraphicsPipelineCreateFunction =
std::function<std::shared_ptr<GraphicsPipeline>(GraphicsPipelineBuilder &,
DescriptorSetLayoutBuilder &,
DescriptorSetAllocator &,
DescriptorSetUpdateBuilder &)>;
using GraphicsPipelineCreateFunction = std::function<std::shared_ptr<GraphicsPipeline>(GraphicsPipelineBuilder &)>;

/// The callables to create the graphics pipelines used in the rendergraph
std::vector<GraphicsPipelineCreateFunction> m_pipeline_create_functions;
Expand All @@ -124,6 +121,15 @@ class RenderGraph {
/// TODO: Explain how textures are treated equally here
std::vector<std::shared_ptr<Texture>> m_textures;

// ---------------------------------------------------------------------------------------------------------
// DESCRIPTORS
// ---------------------------------------------------------------------------------------------------------
// @note Descriptors are not associated with a pipeline or a pass inside of rendergraph
std::vector<std::tuple<std::function<void(DescriptorSetLayoutBuilder &)>,
std::function<void(DescriptorSetAllocator &)>,
std::function<void(DescriptorSetUpdateBuilder &)>>>
m_resource_descriptors;

// TODO: Add @exception to documentation of other methods/code parts!

/// The rendergraph must not have any cycles in it!
Expand All @@ -134,6 +140,8 @@ class RenderGraph {
/// @param cmd_buf The command buffer to record into
void create_buffers();

void create_descriptor_set_layouts();

/// Create the graphics passes
void create_graphics_passes();

Expand Down Expand Up @@ -211,6 +219,17 @@ class RenderGraph {
[[nodiscard]] std::shared_ptr<Buffer>
add_buffer(std::string buffer_name, BufferType buffer_type, std::function<void()> on_update);

///
void allocate_descriptor_sets();

/// Add a descriptor to rendergraph
/// @param on_create_descriptor_set_layout
/// @param on_allocate_descriptor_set
/// @param on_update_descriptor_set
void add_resource_descriptor(std::function<void(DescriptorSetLayoutBuilder &)> on_create_descriptor_set_layout,
std::function<void(DescriptorSetAllocator &)> on_allocate_descriptor_set,
std::function<void(DescriptorSetUpdateBuilder &)> on_update_descriptor_set);

/// Add a texture which will be initialized inside of rendergraph (not outside of it)
/// @param texture_name The name of the texture
/// @param usage
Expand Down
24 changes: 13 additions & 11 deletions src/vulkan-renderer/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,20 +479,22 @@ void Application::setup_render_graph() {
using wrapper::descriptors::DescriptorSetUpdateBuilder;
using wrapper::pipelines::GraphicsPipelineBuilder;

m_render_graph->add_resource_descriptor(
[&](DescriptorSetLayoutBuilder &descriptor_set_layout_builder) {
m_descriptor_set_layout =
descriptor_set_layout_builder.add_uniform_buffer(VK_SHADER_STAGE_VERTEX_BIT).build("Octree");
},
[&](DescriptorSetAllocator &descriptor_set_allocator) {
m_descriptor_set = descriptor_set_allocator.allocate(m_descriptor_set_layout);
},
[&](DescriptorSetUpdateBuilder &descriptor_set_update_builder) {
descriptor_set_update_builder.add_uniform_buffer_update(m_descriptor_set, m_uniform_buffer).update();
});

// TODO: Move octree renderer out of here
// TODO: How to associate data of rendergraph with renderers? Should renderers only do the setup?
// TODO: API style like m_render_graph->add_renderer(octree_renderer)->add_renderer(imgui_renderer);?
m_render_graph->add_graphics_pipeline([&](GraphicsPipelineBuilder &graphics_pipeline_builder,
DescriptorSetLayoutBuilder &descriptor_set_layout_builder,
DescriptorSetAllocator &descriptor_set_allocator,
DescriptorSetUpdateBuilder &descriptor_set_update_builder) {
m_descriptor_set_layout =
descriptor_set_layout_builder.add_uniform_buffer(VK_SHADER_STAGE_VERTEX_BIT).build("Octree");

m_descriptor_set = descriptor_set_allocator.allocate(m_descriptor_set_layout);

descriptor_set_update_builder.add_uniform_buffer_update(m_descriptor_set, m_uniform_buffer).update();

m_render_graph->add_graphics_pipeline([&](GraphicsPipelineBuilder &graphics_pipeline_builder) {
m_octree_pipeline = graphics_pipeline_builder
.set_vertex_input_bindings({
{
Expand Down
48 changes: 35 additions & 13 deletions src/vulkan-renderer/render-graph/render_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ RenderGraph::add_buffer(std::string buffer_name, const BufferType buffer_type, s
return m_buffers.back();
}

void RenderGraph::allocate_descriptor_sets() {
for (const auto &descriptor : m_resource_descriptors) {
// Call on_update_descriptor_set for each descriptor
std::invoke(std::get<1>(descriptor), m_descriptor_set_allocator);
}
}

void RenderGraph::add_resource_descriptor(
std::function<void(DescriptorSetLayoutBuilder &)> on_create_descriptor_set_layout,
std::function<void(DescriptorSetAllocator &)> on_allocate_descriptor_set,
std::function<void(DescriptorSetUpdateBuilder &)> on_update_descriptor_set) {
// NOTE: emplace_back directly constructs the tuple in place, no need for push_back and std::make_tuple
m_resource_descriptors.emplace_back(std::move(on_create_descriptor_set_layout),
std::move(on_allocate_descriptor_set), std::move(on_update_descriptor_set));
}

std::shared_ptr<Texture>
RenderGraph::add_texture(std::string texture_name, const TextureUsage usage, const VkFormat format) {
m_textures.emplace_back(std::make_shared<Texture>(m_device, std::move(texture_name), usage, format));
Expand All @@ -56,6 +72,9 @@ void RenderGraph::compile() {
determine_pass_order();
create_buffers();
create_textures();
create_descriptor_set_layouts();
allocate_descriptor_sets();
update_descriptor_sets();
create_graphics_passes();
create_graphics_pipelines();
}
Expand All @@ -69,6 +88,13 @@ void RenderGraph::create_buffers() {
});
}

void RenderGraph::create_descriptor_set_layouts() {
for (const auto &descriptor : m_resource_descriptors) {
// Call on_update_descriptor_set for each descriptor
std::invoke(std::get<0>(descriptor), m_descriptor_set_layout_builder);
}
}

void RenderGraph::create_graphics_passes() {
m_graphics_passes.clear();
m_graphics_passes.reserve(m_graphics_pass_create_functions.size());
Expand All @@ -81,8 +107,7 @@ void RenderGraph::create_graphics_pipelines() {
m_graphics_pipelines.clear();
m_graphics_pipelines.reserve(m_pipeline_create_functions.size());
for (const auto &create_func : m_pipeline_create_functions) {
m_graphics_pipelines.emplace_back(create_func(m_graphics_pipeline_builder, m_descriptor_set_layout_builder,
m_descriptor_set_allocator, m_descriptor_set_update_builder));
m_graphics_pipelines.emplace_back(create_func(m_graphics_pipeline_builder));
}
}

Expand Down Expand Up @@ -158,6 +183,7 @@ void RenderGraph::record_command_buffer_for_pass(const CommandBuffer &cmd_buf,
const bool is_first_pass,
const bool is_last_pass,
const std::uint32_t img_index) {
// TODO: Expose pass_index as parameter?
// TODO: Remove img_index and implement swapchain.get_current_image()
// TODO: Or do we need the image index for buffers? (We want to automatically double or triple buffer them)

Expand Down Expand Up @@ -303,6 +329,13 @@ void RenderGraph::update_buffers() {
});
}

void RenderGraph::update_descriptor_sets() {
for (const auto &descriptor : m_resource_descriptors) {
// Call on_update_descriptor_set for each descriptor
std::invoke(std::get<2>(descriptor), m_descriptor_set_update_builder);
}
}

void RenderGraph::update_textures() {
m_device.execute("[RenderGraph::update_textures]", [&](const CommandBuffer &cmd_buf) {
for (const auto &texture : m_textures) {
Expand All @@ -319,17 +352,6 @@ void RenderGraph::update_textures() {
});
}

void RenderGraph::update_descriptor_sets() {
// The problem is here that the binding is determined by the oder we call the add methods of the descriptor
// set layout builder, but that is determined by the order we iterate through buffer and texture reads.
// Those reads would either have to be in one struct or some other ordering must take place!!! If not, this
// will cause trouble if a pass reads from both let's say a uniform buffer and a texture, but the order
// specified in descriptor set layout builder results in a binding order that is incorrect!

// TODO: Implement me!
// TODO: Builder pattern for descriptor writes?
}

void RenderGraph::validate_render_graph() {
if (m_graphics_pass_create_functions.empty()) {
throw std::runtime_error("[RenderGraph::validate_render_graph] Error: No graphics passes in rendergraph!");
Expand Down
23 changes: 12 additions & 11 deletions src/vulkan-renderer/renderers/imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ ImGuiRenderer::ImGuiRenderer(const Device &device,
// Index buffer is already being updated in vertex buffer update lambda...
});

// TODO: Shaders should be part of the renderer, but not the rendergraph itself!
// TODO: Implement a ShaderManager (ShaderCache?) inside of Device wrapper?
m_vertex_shader =
std::make_shared<wrapper::Shader>(m_device, "ImGui", VK_SHADER_STAGE_VERTEX_BIT, "shaders/ui.vert.spv");
Expand Down Expand Up @@ -107,17 +106,19 @@ ImGuiRenderer::ImGuiRenderer(const Device &device,
using wrapper::descriptors::DescriptorSetUpdateBuilder;
using wrapper::pipelines::GraphicsPipelineBuilder;

render_graph.add_graphics_pipeline([&](GraphicsPipelineBuilder &graphics_pipeline_builder,
DescriptorSetLayoutBuilder &descriptor_set_layout_builder,
DescriptorSetAllocator &descriptor_set_allocator,
DescriptorSetUpdateBuilder &descriptor_set_update_builder) {
m_descriptor_set_layout =
descriptor_set_layout_builder.add_combined_image_sampler(VK_SHADER_STAGE_FRAGMENT_BIT).build("ImGui");

m_descriptor_set = descriptor_set_allocator.allocate(m_descriptor_set_layout);

descriptor_set_update_builder.add_combined_image_sampler_update(m_descriptor_set, m_imgui_texture).update();
render_graph.add_resource_descriptor(
[&](DescriptorSetLayoutBuilder &descriptor_set_layout_builder) {
m_descriptor_set_layout =
descriptor_set_layout_builder.add_combined_image_sampler(VK_SHADER_STAGE_FRAGMENT_BIT).build("ImGui");
},
[&](DescriptorSetAllocator &descriptor_set_allocator) {
m_descriptor_set = descriptor_set_allocator.allocate(m_descriptor_set_layout);
},
[&](DescriptorSetUpdateBuilder &descriptor_set_update_builder) {
descriptor_set_update_builder.add_combined_image_sampler_update(m_descriptor_set, m_imgui_texture).update();
});

render_graph.add_graphics_pipeline([&](GraphicsPipelineBuilder &graphics_pipeline_builder) {
m_imgui_pipeline = graphics_pipeline_builder
.set_vertex_input_bindings({
{
Expand Down

0 comments on commit 669c13e

Please sign in to comment.