Skip to content

Commit

Permalink
[render-graph|renderpass] Introduce renderpass wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
IAmNotHanni committed Mar 8, 2023
1 parent 2e0f516 commit 7d2fc47
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 33 deletions.
7 changes: 6 additions & 1 deletion include/inexor/vulkan-renderer/render_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "inexor/vulkan-renderer/wrapper/framebuffer.hpp"
#include "inexor/vulkan-renderer/wrapper/image.hpp"
#include "inexor/vulkan-renderer/wrapper/pipeline_layout.hpp"
#include "inexor/vulkan-renderer/wrapper/renderpass.hpp"
#include "inexor/vulkan-renderer/wrapper/semaphore.hpp"
#include "inexor/vulkan-renderer/wrapper/shader.hpp"
#include "inexor/vulkan-renderer/wrapper/swapchain.hpp"
Expand Down Expand Up @@ -374,8 +375,8 @@ class PhysicalGraphicsStage : public PhysicalStage {
friend RenderGraph;

private:
VkRenderPass m_render_pass{VK_NULL_HANDLE};
std::vector<wrapper::Framebuffer> m_framebuffers;
std::unique_ptr<wrapper::RenderPass> m_render_pass;

public:
explicit PhysicalGraphicsStage(const wrapper::Device &device) : PhysicalStage(device) {}
Expand All @@ -385,6 +386,10 @@ class PhysicalGraphicsStage : public PhysicalStage {

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

[[nodiscard]] VkRenderPass render_pass() const noexcept {
return m_render_pass->render_pass();
}
};

class RenderGraph {
Expand Down
50 changes: 50 additions & 0 deletions include/inexor/vulkan-renderer/wrapper/renderpass.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <vulkan/vulkan_core.h>

#include <string>
#include <vector>

namespace inexor::vulkan_renderer::wrapper {

// Forward declaration
class Device;

/// RAII wrapper for VkRenderPass
class RenderPass {
private:
const Device &m_device;
VkRenderPass m_render_pass{VK_NULL_HANDLE};
std::string m_name;

public:
/// Default constructor
/// @param device The device wrapper
/// @param render_pass_ci The render pass create info
/// @param name The internal debug name of the render pass
RenderPass(const Device &device, const VkRenderPassCreateInfo &render_pass_ci, std::string name);

/// Overloaded constructor which takes the attachment descriptions, subpass descriptions, and subpass dependencies
/// @param device The device wrapper
/// @param render_pass_ci The render pass create info
/// @param attachments The attachment descriptions
/// @param subpasses The subpass descriptions
/// @param dependencies The dependencies
/// @param name The internal debug name of the render pass
RenderPass(const Device &device, const std::vector<VkAttachmentDescription> &attachments,
const std::vector<VkSubpassDescription> &subpasses, const std::vector<VkSubpassDependency> &dependencies,
std::string name);

RenderPass(const RenderPass &) = delete;
RenderPass(RenderPass &&) noexcept;
~RenderPass();

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

[[nodiscard]] VkRenderPass render_pass() const noexcept {
return m_render_pass;
}
};

} // namespace inexor::vulkan_renderer::wrapper
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ set(INEXOR_SOURCE_FILES
vulkan-renderer/wrapper/instance.cpp
vulkan-renderer/wrapper/pipeline_layout.cpp
vulkan-renderer/wrapper/make_info.cpp
vulkan-renderer/wrapper/renderpass.cpp
vulkan-renderer/wrapper/sampler.cpp
vulkan-renderer/wrapper/semaphore.cpp
vulkan-renderer/wrapper/shader.cpp
Expand Down
54 changes: 22 additions & 32 deletions src/vulkan-renderer/render_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ PhysicalStage::~PhysicalStage() {
vkDestroyPipeline(m_device.device(), m_pipeline, nullptr);
}

PhysicalGraphicsStage::~PhysicalGraphicsStage() {
vkDestroyRenderPass(m_device.device(), m_render_pass, nullptr);
}
PhysicalGraphicsStage::~PhysicalGraphicsStage() {}

void RenderGraph::build_buffer(const BufferResource &buffer_resource, PhysicalBuffer &physical) const {
// TODO: Don't always create mapped.
Expand Down Expand Up @@ -159,7 +157,7 @@ void RenderGraph::record_command_buffer(const RenderStage *stage, const wrapper:
}

cmd_buf.begin_render_pass(wrapper::make_info<VkRenderPassBeginInfo>({
.renderPass = phys_graphics_stage->m_render_pass,
.renderPass = phys_graphics_stage->m_render_pass->render_pass(),
.framebuffer = phys_graphics_stage->m_framebuffers.at(image_index).get(),
.renderArea{
.extent = m_swapchain.extent(),
Expand Down Expand Up @@ -249,35 +247,27 @@ void RenderGraph::build_render_pass(const GraphicsStage *stage, PhysicalGraphics
attachments.push_back(attachment);
}

// Build a simple subpass that just waits for the output colour vector to be written by the fragment shader. In the
// future, we may want to make use of subpasses more.
const VkSubpassDependency subpass_dependency{
.srcSubpass = VK_SUBPASS_EXTERNAL,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
const std::vector<VkSubpassDescription> subpasses{
{
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.colorAttachmentCount = static_cast<std::uint32_t>(colour_refs.size()),
.pColorAttachments = colour_refs.data(),
.pDepthStencilAttachment = !depth_refs.empty() ? depth_refs.data() : nullptr,
},
};

const VkSubpassDescription subpass_description{
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.colorAttachmentCount = static_cast<std::uint32_t>(colour_refs.size()),
.pColorAttachments = colour_refs.data(),
.pDepthStencilAttachment = !depth_refs.empty() ? depth_refs.data() : nullptr,
// Build a simple subpass that just waits for the output colour vector to be written by the fragment shader
const std::vector<VkSubpassDependency> dependencies{
{
.srcSubpass = VK_SUBPASS_EXTERNAL,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
},
};

const auto render_pass_ci = wrapper::make_info<VkRenderPassCreateInfo>({
.attachmentCount = static_cast<std::uint32_t>(attachments.size()),
.pAttachments = attachments.data(),
.subpassCount = 1,
.pSubpasses = &subpass_description,
.dependencyCount = 1,
.pDependencies = &subpass_dependency,
});

if (const auto result = vkCreateRenderPass(m_device.device(), &render_pass_ci, nullptr, &physical.m_render_pass);
result != VK_SUCCESS) {
throw VulkanException("Error: vkCreateRenderPass failed for renderpass " + stage->name() + " !", result);
}
physical.m_render_pass =
std::make_unique<wrapper::RenderPass>(m_device, attachments, subpasses, dependencies, "renderpass");
}

void RenderGraph::build_graphics_pipeline(const GraphicsStage *stage, PhysicalGraphicsStage &physical) const {
Expand Down Expand Up @@ -383,7 +373,7 @@ void RenderGraph::build_graphics_pipeline(const GraphicsStage *stage, PhysicalGr
.pDepthStencilState = &depth_stencil,
.pColorBlendState = &blend_state,
.layout = physical.pipeline_layout(),
.renderPass = physical.m_render_pass,
.renderPass = physical.m_render_pass->render_pass(),
});

// TODO: Pipeline caching (basically load the render graph from a file)
Expand Down Expand Up @@ -489,8 +479,8 @@ void RenderGraph::compile(const RenderResource *target) {
for (const auto *image : images) {
image_views.push_back(image->image_view());
}
physical.m_framebuffers.emplace_back(m_device, physical.m_render_pass, image_views, m_swapchain,
"Framebuffer");
physical.m_framebuffers.emplace_back(m_device, physical.m_render_pass->render_pass(), image_views,
m_swapchain, "Framebuffer");
image_views.clear();
}
}
Expand Down
38 changes: 38 additions & 0 deletions src/vulkan-renderer/wrapper/renderpass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "inexor/vulkan-renderer/wrapper/renderpass.hpp"

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

#include <utility>

namespace inexor::vulkan_renderer::wrapper {

RenderPass::RenderPass(const Device &device, const VkRenderPassCreateInfo &render_pass_ci, std::string name)
: m_device(device), m_name(std::move(name)) {
m_device.create_render_pass(render_pass_ci, &m_render_pass, m_name);
}

RenderPass::RenderPass(const Device &device, const std::vector<VkAttachmentDescription> &attachments,
const std::vector<VkSubpassDescription> &subpasses,
const std::vector<VkSubpassDependency> &dependencies, std::string name)
: RenderPass(device,
wrapper::make_info<VkRenderPassCreateInfo>({
.attachmentCount = static_cast<std::uint32_t>(attachments.size()),
.pAttachments = attachments.data(),
.subpassCount = static_cast<std::uint32_t>(subpasses.size()),
.pSubpasses = subpasses.data(),
.dependencyCount = static_cast<std::uint32_t>(dependencies.size()),
.pDependencies = dependencies.data(),
}),
std::move(name)) {}

RenderPass::RenderPass(RenderPass &&other) noexcept : m_device(other.m_device) {
m_render_pass = std::exchange(other.m_render_pass, VK_NULL_HANDLE);
m_name = std::move(other.m_name);
}

RenderPass::~RenderPass() {
vkDestroyRenderPass(m_device.device(), m_render_pass, nullptr);
}

} // namespace inexor::vulkan_renderer::wrapper

0 comments on commit 7d2fc47

Please sign in to comment.