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 16, 2024
1 parent aa96b41 commit 9f7245b
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 86 deletions.
1 change: 1 addition & 0 deletions include/inexor/vulkan-renderer/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class Application {
VkDescriptorSet m_descriptor_set{VK_NULL_HANDLE};

std::shared_ptr<wrapper::pipelines::GraphicsPipeline> m_octree_pipeline;
std::shared_ptr<render_graph::GraphicsPass> m_octree_pass;

struct ModelViewPerspectiveMatrices {
glm::mat4 model{1.0f};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ class GraphicsPassBuilder {
private:
/// Add members which describe data related to graphics passes here
std::function<void(const CommandBuffer &)> m_on_record_cmd_buffer{};

/// The color attachments of the graphics pass
std::vector<Attachment> m_color_attachments{};
/// The depth attachment of the graphics pass
Attachment m_depth_attachment{};
/// The stencil attachment of the graphics pass
Attachment m_stencil_attachment{};

/// The graphics passes which are read by this graphics pass. Based on this, rendergraph can automatically determine
/// the correct pass order based on depth first search algorithm (DFS)
std::vector<std::weak_ptr<GraphicsPass>> m_graphics_pass_reads{};

/// Reset all data of the graphics pass builder
void reset();

Expand Down Expand Up @@ -68,7 +73,12 @@ class GraphicsPassBuilder {
/// Build the graphics pass
/// @param name The name of the graphics pass
/// @return The graphics pass that was just created
[[nodiscard]] GraphicsPass build(std::string name);
[[nodiscard]] std::shared_ptr<GraphicsPass> build(std::string name);

/// Specify that this graphics pass A reads from another graphics pass B, meaning B should be rendered before A
/// @param graphics_pass The graphics pass which is read by this graphics pass
/// @return A const reference to the this pointer (allowing method calls to be chained)
[[nodiscard]] GraphicsPassBuilder &reads_from(std::weak_ptr<GraphicsPass> graphics_pass);

/// Set the function which will be called when the command buffer for rendering of the pass is being recorded
/// @param on_record_cmd_buffer The command buffer recording function
Expand Down
4 changes: 2 additions & 2 deletions include/inexor/vulkan-renderer/render-graph/render_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ class RenderGraph {
/// The graphics pass builder of the rendergraph
GraphicsPassBuilder m_graphics_pass_builder{};
/// In these callback functions, the graphics passes will be created
using OnCreateGraphicsPass = std::function<GraphicsPass(GraphicsPassBuilder &)>;
using OnCreateGraphicsPass = std::function<std::shared_ptr<GraphicsPass>(GraphicsPassBuilder &)>;
/// The graphics pass create functions
std::vector<OnCreateGraphicsPass> m_graphics_pass_create_functions;
/// The graphics passes used in the rendergraph
std::vector<GraphicsPass> m_graphics_passes;
std::vector<std::shared_ptr<GraphicsPass>> m_graphics_passes;

/// -----------------------------------------------------------------------------------------------------------------
/// GRAPHICS PIPELINES
Expand Down
4 changes: 3 additions & 1 deletion include/inexor/vulkan-renderer/renderers/imgui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ class ImGuiRenderer {
std::weak_ptr<render_graph::Buffer> m_index_buffer;
std::weak_ptr<render_graph::Buffer> m_vertex_buffer;
std::weak_ptr<render_graph::Texture> m_imgui_texture;
std::shared_ptr<wrapper::pipelines::GraphicsPipeline> m_imgui_pipeline;
std::shared_ptr<render_graph::GraphicsPass> m_imgui_pass;

std::shared_ptr<wrapper::Shader> m_vertex_shader;
std::shared_ptr<wrapper::Shader> m_fragment_shader;
std::shared_ptr<wrapper::pipelines::GraphicsPipeline> m_imgui_pipeline;

VkDescriptorSetLayout m_descriptor_set_layout{VK_NULL_HANDLE};
VkDescriptorSet m_descriptor_set{VK_NULL_HANDLE};
Expand Down
61 changes: 24 additions & 37 deletions src/vulkan-renderer/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,23 +419,16 @@ void Application::run() {
}

void Application::setup_render_graph() {
// TODO: Move to OctreeRenderer and ImGuiRenderer!
// TODO: Move this to rendergraph header file? (Can we then use it here?)
using render_graph::BufferType;
using render_graph::BufferType::INDEX_BUFFER;
using render_graph::BufferType::UNIFORM_BUFFER;
using render_graph::BufferType::VERTEX_BUFFER;
using render_graph::TextureUsage::BACK_BUFFER;
using render_graph::TextureUsage::DEPTH_STENCIL_BUFFER;

const auto swapchain_extent = m_swapchain->extent();
m_back_buffer = m_render_graph->add_texture("Color", BACK_BUFFER, m_swapchain->image_format(),
swapchain_extent.width, swapchain_extent.height);
m_back_buffer =
m_render_graph->add_texture("Color", render_graph::TextureUsage::BACK_BUFFER, m_swapchain->image_format(),
swapchain_extent.width, swapchain_extent.height);

m_depth_buffer = m_render_graph->add_texture("Depth", DEPTH_STENCIL_BUFFER, VK_FORMAT_D32_SFLOAT_S8_UINT,
swapchain_extent.width, swapchain_extent.height);
m_depth_buffer =
m_render_graph->add_texture("Depth", render_graph::TextureUsage::DEPTH_STENCIL_BUFFER,
VK_FORMAT_D32_SFLOAT_S8_UINT, swapchain_extent.width, swapchain_extent.height);

m_vertex_buffer = m_render_graph->add_buffer("Octree", VERTEX_BUFFER, [&]() {
m_vertex_buffer = m_render_graph->add_buffer("Octree", render_graph::BufferType::VERTEX_BUFFER, [&]() {
// If the key N was pressed once, generate a new octree
if (m_input_data->was_key_pressed_once(GLFW_KEY_N)) {
load_octree_geometry(false);
Expand All @@ -452,7 +445,7 @@ void Application::setup_render_graph() {

// Note that the index buffer is updated together with the vertex buffer to keep data consistent
// This means for m_index_buffer, on_init and on_update are defaulted to std::nullopt here!
m_index_buffer = m_render_graph->add_buffer("Octree", INDEX_BUFFER, [&]() {
m_index_buffer = m_render_graph->add_buffer("Octree", render_graph::BufferType::INDEX_BUFFER, [&]() {
// Request update of the octree index buffer
m_index_buffer.lock()->request_update(m_octree_indices);
});
Expand All @@ -464,32 +457,27 @@ void Application::setup_render_graph() {
m_vertex_buffer.lock()->request_update(m_octree_vertices);
m_index_buffer.lock()->request_update(m_octree_indices);

m_uniform_buffer = m_render_graph->add_buffer("Matrices", UNIFORM_BUFFER, [&]() {
m_uniform_buffer = m_render_graph->add_buffer("Matrices", render_graph::BufferType::UNIFORM_BUFFER, [&]() {
m_mvp_matrices.view = m_camera->view_matrix();
m_mvp_matrices.proj = m_camera->perspective_matrix();
m_mvp_matrices.proj[1][1] *= -1;
m_uniform_buffer.lock()->request_update(m_mvp_matrices);
});

using wrapper::descriptors::DescriptorSetAllocator;
using wrapper::descriptors::DescriptorSetLayoutBuilder;
using wrapper::descriptors::DescriptorSetUpdateBuilder;
m_render_graph->add_resource_descriptor(
[&](DescriptorSetLayoutBuilder &builder) {
[&](wrapper::descriptors::DescriptorSetLayoutBuilder &builder) {
m_descriptor_set_layout = builder.add_uniform_buffer(VK_SHADER_STAGE_VERTEX_BIT).build("Octree");
},
[&](DescriptorSetAllocator &allocator) {
[&](wrapper::descriptors::DescriptorSetAllocator &allocator) {
m_descriptor_set = allocator.allocate("Octree", m_descriptor_set_layout);
},
[&](DescriptorSetUpdateBuilder &builder) {
[&](wrapper::descriptors::DescriptorSetUpdateBuilder &builder) {
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);?
using wrapper::pipelines::GraphicsPipelineBuilder;
m_render_graph->add_graphics_pipeline([&](GraphicsPipelineBuilder &builder) {
// TODO: Implement octree renderer

m_render_graph->add_graphics_pipeline([&](wrapper::pipelines::GraphicsPipelineBuilder &builder) {
m_octree_pipeline = builder
.set_vertex_input_bindings({
{
Expand All @@ -498,8 +486,7 @@ void Application::setup_render_graph() {
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
},
})
// TODO! Fix me!
.set_multisampling(m_device->get_max_usable_sample_count(), 1.0f)
.set_multisampling(m_device->get_max_usable_sample_count(), 0.25f)
.add_default_color_blend_attachment()
.add_color_attachment(m_swapchain->image_format())
.set_depth_attachment_format(VK_FORMAT_D32_SFLOAT_S8_UINT)
Expand All @@ -523,23 +510,23 @@ void Application::setup_render_graph() {
.uses_shader(m_octree_vert)
.uses_shader(m_octree_frag)
.build("Octree");
return m_octree_pipeline;
});

using wrapper::commands::CommandBuffer;
auto on_record_cmd_buffer = [&](const CommandBuffer &cmd_buf) {
auto on_record_cmd_buffer = [&](const wrapper::commands::CommandBuffer &cmd_buf) {
cmd_buf.bind_pipeline(m_octree_pipeline)
.bind_descriptor_set(m_descriptor_set, m_octree_pipeline)
.bind_vertex_buffer(m_vertex_buffer)
.bind_index_buffer(m_index_buffer)
.draw_indexed(static_cast<std::uint32_t>(m_octree_indices.size()));
};

using render_graph::GraphicsPassBuilder;
m_render_graph->add_graphics_pass([&](GraphicsPassBuilder &builder) {
return builder.add_color_attachment(m_back_buffer, VkClearValue{1.0f, 0.0f, 0.0f, 1.0f})
.add_depth_attachment(m_depth_buffer)
.set_on_record(std::move(on_record_cmd_buffer))
.build("Octree");
m_render_graph->add_graphics_pass([&](render_graph::GraphicsPassBuilder &builder) {
m_octree_pass = builder.add_color_attachment(m_back_buffer, VkClearValue{1.0f, 0.0f, 0.0f, 1.0f})
.add_depth_attachment(m_depth_buffer)
.set_on_record(std::move(on_record_cmd_buffer))
.build("Octree");
return m_octree_pass;
});

// TODO: We don't need to recreate the imgui overlay when swapchain is recreated, use a .recreate() method instead?
Expand Down
26 changes: 19 additions & 7 deletions src/vulkan-renderer/render-graph/graphics_pass_builder.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "inexor/vulkan-renderer/render-graph/graphics_pass_builder.hpp"

#include <utility>

namespace inexor::vulkan_renderer::render_graph {

GraphicsPassBuilder::GraphicsPassBuilder() {
Expand All @@ -10,7 +12,7 @@ GraphicsPassBuilder &GraphicsPassBuilder::add_color_attachment(std::weak_ptr<Tex
std::optional<VkClearValue> clear_value) {
if (color_attachment.expired()) {
throw std::invalid_argument(
"[GraphicsPassBuilder::add_color_attachment] Error: 'color_attachment' is expired!");
"[GraphicsPassBuilder::add_color_attachment] Error: 'color_attachment' is an invalid pointer!");
}
m_color_attachments.emplace_back(std::move(color_attachment), std::move(clear_value));
return *this;
Expand All @@ -19,7 +21,8 @@ GraphicsPassBuilder &GraphicsPassBuilder::add_color_attachment(std::weak_ptr<Tex
GraphicsPassBuilder &GraphicsPassBuilder::add_depth_attachment(std::weak_ptr<Texture> depth_attachment,
std::optional<VkClearValue> clear_value) {
if (depth_attachment.expired()) {
throw std::invalid_argument("[GraphicsPassBuilder::enable_depth_test] Error: 'depth_buffer' is expired!");
throw std::invalid_argument(
"[GraphicsPassBuilder::enable_depth_test] Error: 'depth_buffer' is an invalid pointer!");
}
m_depth_attachment = Attachment(std::move(depth_attachment), std::move(clear_value));
return *this;
Expand All @@ -29,25 +32,34 @@ GraphicsPassBuilder &GraphicsPassBuilder::add_stencil_attachment(std::weak_ptr<T
std::optional<VkClearValue> clear_value) {
if (stencil_attachment.expired()) {
throw std::invalid_argument(
"[GraphicsPassBuilder::add_stencil_attachment] Error: 'stencil_attachment' is expired!");
"[GraphicsPassBuilder::add_stencil_attachment] Error: 'stencil_attachment' is an invalid pointer!");
}
m_stencil_attachment = Attachment(std::move(stencil_attachment), std::move(clear_value));
return *this;
}

GraphicsPass GraphicsPassBuilder::build(std::string name) {
auto graphics_pass =
GraphicsPass(std::move(name), std::move(m_on_record_cmd_buffer), std::move(m_color_attachments),
std::move(m_depth_attachment), std::move(m_stencil_attachment));
std::shared_ptr<GraphicsPass> GraphicsPassBuilder::build(std::string name) {
auto graphics_pass = std::make_shared<GraphicsPass>(std::move(name), std::move(m_on_record_cmd_buffer),
std::move(m_color_attachments), std::move(m_depth_attachment),
std::move(m_stencil_attachment));
reset();
return graphics_pass;
}

GraphicsPassBuilder &GraphicsPassBuilder::reads_from(std::weak_ptr<GraphicsPass> graphics_pass) {
if (graphics_pass.expired()) {
throw std::invalid_argument("[GraphicsPassBuilder::reads_from] Error: 'graphics_pass' is an invalid pointer!");
}
m_graphics_pass_reads.push_back(std::move(graphics_pass));
return *this;
}

void GraphicsPassBuilder::reset() {
m_on_record_cmd_buffer = {};
m_color_attachments = {};
m_depth_attachment = {};
m_stencil_attachment = {};
m_graphics_pass_reads.clear();
}

GraphicsPassBuilder &
Expand Down
26 changes: 13 additions & 13 deletions src/vulkan-renderer/render-graph/render_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,32 +134,32 @@ void RenderGraph::create_rendering_infos() {
});
};
// Fill the color attachments
pass.m_color_attachment_infos.reserve(pass.m_color_attachments.size());
for (const auto &color_attachment : pass.m_color_attachments) {
pass.m_color_attachment_infos.push_back(fill_rendering_info(color_attachment));
pass->m_color_attachment_infos.reserve(pass->m_color_attachments.size());
for (const auto &color_attachment : pass->m_color_attachments) {
pass->m_color_attachment_infos.push_back(fill_rendering_info(color_attachment));
}
// Fill the color attachment (if specified)
const bool has_depth_attachment = !pass.m_depth_attachment.first.expired();
const bool has_depth_attachment = !pass->m_depth_attachment.first.expired();
if (has_depth_attachment) {
pass.m_depth_attachment_info = fill_rendering_info(pass.m_depth_attachment);
pass->m_depth_attachment_info = fill_rendering_info(pass->m_depth_attachment);
}
// Fill the stencil attachment (if specified)
const bool has_stencil_attachment = !pass.m_stencil_attachment.first.expired();
const bool has_stencil_attachment = !pass->m_stencil_attachment.first.expired();
if (has_stencil_attachment) {
pass.m_stencil_attachment_info = fill_rendering_info(pass.m_stencil_attachment);
pass->m_stencil_attachment_info = fill_rendering_info(pass->m_stencil_attachment);
}
// We store all this data in the rendering info in the graphics pass itself
// The advantage of this is that we don't have to fill this during the actual rendering
pass.m_rendering_info = std::move(wrapper::make_info<VkRenderingInfo>({
pass->m_rendering_info = std::move(wrapper::make_info<VkRenderingInfo>({
.renderArea =
{
.extent = m_swapchain.extent(),
},
.layerCount = 1,
.colorAttachmentCount = static_cast<std::uint32_t>(pass.m_color_attachment_infos.size()),
.pColorAttachments = pass.m_color_attachment_infos.data(),
.pDepthAttachment = has_depth_attachment ? &pass.m_depth_attachment_info : nullptr,
.pStencilAttachment = has_stencil_attachment ? &pass.m_stencil_attachment_info : nullptr,
.colorAttachmentCount = static_cast<std::uint32_t>(pass->m_color_attachment_infos.size()),
.pColorAttachments = pass->m_color_attachment_infos.data(),
.pDepthAttachment = has_depth_attachment ? &pass->m_depth_attachment_info : nullptr,
.pStencilAttachment = has_stencil_attachment ? &pass->m_stencil_attachment_info : nullptr,
}));
}
}
Expand Down Expand Up @@ -218,7 +218,7 @@ void RenderGraph::record_command_buffers(const CommandBuffer &cmd_buf, const std
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);

for (const auto &pass : m_graphics_passes) {
record_command_buffer_for_pass(cmd_buf, pass);
record_command_buffer_for_pass(cmd_buf, *pass);
}
// Change the layout of the swapchain image to make it ready for presenting
cmd_buf.change_image_layout(m_swapchain.image(img_index), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Expand Down
Loading

0 comments on commit 9f7245b

Please sign in to comment.