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 159e0d0 commit 24ae683
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 61 deletions.
10 changes: 8 additions & 2 deletions include/inexor/vulkan-renderer/render-graph/image.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ class Image {
VkImage m_img{VK_NULL_HANDLE};
VkImageView m_img_view{VK_NULL_HANDLE};
VmaAllocation m_alloc{VK_NULL_HANDLE};

VmaAllocationInfo m_alloc_info{};
VmaAllocationCreateInfo m_alloc_ci{};

const VmaAllocationCreateInfo m_alloc_ci{
.usage = VMA_MEMORY_USAGE_AUTO,
};

/// The combined image sampler for the texture
/// This is only relevant if the texture is used as TextureUsage::NORMAL
Expand All @@ -60,7 +64,9 @@ class Image {
public:
/// Default constructor
/// @param device The device wrapper
Image(const Device &device);
/// @param name The name of the Image
Image(const Device &device, std::string name);

Image(const Image &) = delete;
Image(Image &&) noexcept;
~Image();
Expand Down
5 changes: 3 additions & 2 deletions include/inexor/vulkan-renderer/render-graph/render_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,7 @@ class RenderGraph {

/// Record all command buffers required for the passes
/// @param cmd_buf The command buffer to record all passes with
/// @param img_index The swapchain image index
void record_command_buffers(const CommandBuffer &cmd_buf, std::uint32_t img_index);
void record_command_buffers(const CommandBuffer &cmd_buf);

/// Update the vertex-, index-, and uniform-buffers
/// @note If a uniform buffer has been updated, an update of the associated descriptor set will be performed
Expand Down Expand Up @@ -304,6 +303,7 @@ class RenderGraph {
/// @param texture_name The name of the texture
/// @param usage The usage of the texture inside of rendergraph
/// @param format The format of the texture
/// @param sample_count The sample count of the texture
/// @param on_init The texture initialization function
/// @param on_update The texture update function
/// @return A weak pointer to the texture that was created
Expand All @@ -312,6 +312,7 @@ class RenderGraph {
VkFormat format,
std::uint32_t width,
std::uint32_t height,
VkSampleCountFlagBits sample_count = VK_SAMPLE_COUNT_1_BIT,
std::optional<std::function<void()>> on_init = std::nullopt,
std::optional<std::function<void()>> on_update = std::nullopt);

Expand Down
2 changes: 2 additions & 0 deletions include/inexor/vulkan-renderer/render-graph/texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class Texture {
/// @param format The format of the texture
/// @param width The width of the texture
/// @param height The height of the texture
/// @param sample_count The sample count of the texture
/// @param on_init The initialization function of the texture
/// @param on_update The update function of the texture
Texture(const Device &device,
Expand All @@ -116,6 +117,7 @@ class Texture {
VkFormat format,
std::uint32_t width,
std::uint32_t height,
VkSampleCountFlagBits sample_count,
std::optional<std::function<void()>> on_init = std::nullopt,
std::optional<std::function<void()>> on_update = std::nullopt);

Expand Down
6 changes: 2 additions & 4 deletions include/inexor/vulkan-renderer/wrapper/swapchain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,14 @@ namespace inexor::vulkan_renderer::render_graph {
class RenderGraph;
} // namespace inexor::vulkan_renderer::render_graph

// Using declaration
using inexor::vulkan_renderer::render_graph::RenderGraph;

namespace inexor::vulkan_renderer::wrapper {

// Forward declaration
class Device;

/// RAII wrapper class for swapchains
class Swapchain {
friend class RenderGraph;
friend class render_graph::RenderGraph;

private:
Device &m_device;
Expand All @@ -41,6 +38,7 @@ class Swapchain {
std::unique_ptr<synchronization::Semaphore> m_img_available;
bool m_vsync_enabled{false};
std::uint32_t m_img_index;
VkImage m_current_img{VK_NULL_HANDLE};
VkImageView m_current_img_view{VK_NULL_HANDLE};

/// Call vkGetSwapchainImagesKHR
Expand Down
12 changes: 6 additions & 6 deletions src/vulkan-renderer/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,13 +420,13 @@ void Application::run() {

void Application::setup_render_graph() {
const auto swapchain_extent = m_swapchain->extent();
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_back_buffer = m_render_graph->add_texture("Color", render_graph::TextureUsage::BACK_BUFFER,
m_swapchain->image_format(), swapchain_extent.width,
swapchain_extent.height, m_device->get_max_usable_sample_count());

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_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_device->get_max_usable_sample_count());

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
Expand Down
12 changes: 5 additions & 7 deletions src/vulkan-renderer/render-graph/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ void Buffer::create(const CommandBuffer &cmd_buf) {
throw VulkanException("Error: vmaCreateBuffer failed for staging buffer " + m_name + " !", result);
}

const std::string staging_buf_name = "staging:" + m_name;
// Set the staging buffer's internal debug name in Vulkan Memory Allocator (VMA)
vmaSetAllocationName(m_device.allocator(), m_staging_alloc, m_name.c_str());
vmaSetAllocationName(m_device.allocator(), m_staging_alloc, staging_buf_name.c_str());
// Set the staging buffer's internal debug name through Vulkan debug utils
m_device.set_debug_name(m_staging_buffer, m_name);
m_device.set_debug_name(m_staging_buffer, staging_buf_name);

// Copy the memory into the staging buffer
std::memcpy(m_staging_alloc_info.pMappedData, m_src_data, m_src_data_size);
Expand Down Expand Up @@ -153,11 +154,8 @@ void Buffer::destroy() {
}

void Buffer::request_update(void *src_data, const std::size_t src_data_size) {
if (src_data == nullptr) {
throw std::invalid_argument("Error: Update of buffer resource failed (data pointer is nullptr)!");
}
if (src_data_size == 0) {
throw std::invalid_argument("Error: Update of buffer resource failed (data size is 0)!");
if (src_data == nullptr || src_data_size == 0) {
return;
}
m_src_data = src_data;
m_src_data_size = src_data_size;
Expand Down
8 changes: 7 additions & 1 deletion src/vulkan-renderer/render-graph/graphics_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ GraphicsPass::GraphicsPass(std::string name,
m_stencil_attachment(std::move(stencil_attachment)) {}

GraphicsPass::GraphicsPass(GraphicsPass &&other) noexcept {
// TODO: Fix me!
m_name = std::move(other.m_name);
m_on_record_cmd_buffer = std::move(other.m_on_record_cmd_buffer);
m_color_attachments = std::move(other.m_color_attachments);
m_depth_attachment = std::move(other.m_depth_attachment);
m_stencil_attachment = std::move(other.m_stencil_attachment);
m_descriptor_set_layout = std::exchange(other.m_descriptor_set_layout, nullptr);
m_descriptor_set = std::exchange(other.m_descriptor_set, VK_NULL_HANDLE);
m_rendering_info = std::move(other.m_rendering_info);
m_color_attachment_infos = std::move(other.m_color_attachment_infos);
m_depth_attachment_info = std::move(other.m_depth_attachment_info);
m_stencil_attachment_info = std::move(other.m_stencil_attachment_info);
}

} // namespace inexor::vulkan_renderer::render_graph
2 changes: 1 addition & 1 deletion src/vulkan-renderer/render-graph/graphics_pass_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void GraphicsPassBuilder::reset() {

GraphicsPassBuilder &
GraphicsPassBuilder::set_on_record(std::function<void(const CommandBuffer &)> on_record_cmd_buffer) {
on_record_cmd_buffer = std::move(on_record_cmd_buffer);
m_on_record_cmd_buffer = std::move(on_record_cmd_buffer);
return *this;
}

Expand Down
13 changes: 9 additions & 4 deletions src/vulkan-renderer/render-graph/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@

namespace inexor::vulkan_renderer::render_graph {

Image::Image(const Device &device) : m_device(device) {}

Image::Image(Image &&other) noexcept : m_device(other.m_device) {
// TODO: Fix me!
Image::Image(const Device &device, std::string name) : m_device(device), m_name(std::move(name)) {}

Image::Image(Image &&other) noexcept : m_device(other.m_device), m_alloc_ci(other.m_alloc_ci) {
other.m_name = std::move(other.m_name);
m_img = std::exchange(other.m_img, VK_NULL_HANDLE);
m_img_view = std::exchange(other.m_img_view, VK_NULL_HANDLE);
m_alloc = std::exchange(other.m_alloc, VK_NULL_HANDLE);
m_alloc_info = other.m_alloc_info;
m_sampler = std::exchange(other.m_sampler, nullptr);
}

Image::~Image() {
Expand Down
94 changes: 83 additions & 11 deletions src/vulkan-renderer/render-graph/render_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ std::weak_ptr<Texture> RenderGraph::add_texture(std::string texture_name,
const VkFormat format,
const std::uint32_t width,
const std::uint32_t height,
const VkSampleCountFlagBits sample_count,
std::optional<std::function<void()>> on_init,
std::optional<std::function<void()>> on_update) {
m_textures.emplace_back(std::make_shared<Texture>(m_device, std::move(texture_name), usage, format, width, height,
std::move(on_init), std::move(on_update)));
sample_count, std::move(on_init), std::move(on_update)));
return m_textures.back();
}

Expand Down Expand Up @@ -113,41 +114,108 @@ void RenderGraph::create_rendering_infos() {
const auto img_layout = [&]() -> VkImageLayout {
switch (attach_ptr->m_usage) {
case TextureUsage::BACK_BUFFER:
case TextureUsage::NORMAL: {
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
case TextureUsage::DEPTH_STENCIL_BUFFER: {
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
default:
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
return VK_IMAGE_LAYOUT_UNDEFINED;
}
}(); // Invoke the lambda, not just define it!

auto is_integer_format = [](const VkFormat format) {
switch (format) {
// 8-bit integer formats
case VK_FORMAT_R8_UINT:
case VK_FORMAT_R8_SINT:
case VK_FORMAT_R8G8_UINT:
case VK_FORMAT_R8G8_SINT:
case VK_FORMAT_R8G8B8_UINT:
case VK_FORMAT_R8G8B8_SINT:
case VK_FORMAT_B8G8R8_UINT:
case VK_FORMAT_B8G8R8_SINT:
case VK_FORMAT_R8G8B8A8_UINT:
case VK_FORMAT_R8G8B8A8_SINT:
case VK_FORMAT_B8G8R8A8_UINT:
case VK_FORMAT_B8G8R8A8_SINT:
case VK_FORMAT_A2R10G10B10_UINT_PACK32:
case VK_FORMAT_A2B10G10R10_UINT_PACK32:

// 16-bit integer formats
case VK_FORMAT_R16_UINT:
case VK_FORMAT_R16_SINT:
case VK_FORMAT_R16G16_UINT:
case VK_FORMAT_R16G16_SINT:
case VK_FORMAT_R16G16B16_UINT:
case VK_FORMAT_R16G16B16_SINT:
case VK_FORMAT_R16G16B16A16_UINT:
case VK_FORMAT_R16G16B16A16_SINT:

// 32-bit integer formats
case VK_FORMAT_R32_UINT:
case VK_FORMAT_R32_SINT:
case VK_FORMAT_R32G32_UINT:
case VK_FORMAT_R32G32_SINT:
case VK_FORMAT_R32G32B32_UINT:
case VK_FORMAT_R32G32B32_SINT:
case VK_FORMAT_R32G32B32A32_UINT:
case VK_FORMAT_R32G32B32A32_SINT:

// 64-bit integer formats
case VK_FORMAT_R64_UINT:
case VK_FORMAT_R64_SINT:
case VK_FORMAT_R64G64_UINT:
case VK_FORMAT_R64G64_SINT:
case VK_FORMAT_R64G64B64_UINT:
case VK_FORMAT_R64G64B64_SINT:
case VK_FORMAT_R64G64B64A64_UINT:
case VK_FORMAT_R64G64B64A64_SINT:
return true;

// Non-integer formats
default:
return false;
}
};

// This decides if MSAA is enabled on a per-texture basis
return wrapper::make_info<VkRenderingAttachmentInfo>({
.imageView = attach_ptr->m_img->m_img_view,
.imageLayout = img_layout,
.resolveMode = attach_ptr ? VK_RESOLVE_MODE_MIN_BIT : VK_RESOLVE_MODE_NONE,
.resolveImageView = attach_ptr ? attach_ptr->m_msaa_img->m_img_view : VK_NULL_HANDLE,
.resolveMode = (attach_ptr->m_sample_count > VK_SAMPLE_COUNT_1_BIT)
// The resolve mode must be chosen on whether it's an integer format
? (!is_integer_format(attach_ptr->m_format) ? VK_RESOLVE_MODE_AVERAGE_BIT
: VK_RESOLVE_MODE_MIN_BIT)
: VK_RESOLVE_MODE_NONE,
.resolveImageView = attach_ptr->m_msaa_img ? attach_ptr->m_msaa_img->m_img_view : VK_NULL_HANDLE,
.resolveImageLayout = attach_ptr ? img_layout : VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = attachment.second ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = attachment.second.value_or(VkClearValue{}),
.clearValue = attachment.second ? attachment.second.value() : VkClearValue{},
});
};
// Fill the color attachments

// Reserve memory for the color attachments
pass->m_color_attachment_infos.reserve(pass->m_color_attachments.size());
// Fill the color attachments
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();
if (has_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();
if (has_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>({
Expand All @@ -172,7 +240,10 @@ void RenderGraph::create_textures() {
std::invoke(texture->m_on_init.value());
}
texture->create();
texture->update(cmd_buf);
if (texture->m_usage == TextureUsage::NORMAL) {
// Only external textures are updated, not back or depth buffers used internally in rendergraph
texture->update(cmd_buf);
}
}
});
}
Expand Down Expand Up @@ -200,23 +271,24 @@ void RenderGraph::record_command_buffer_for_pass(const CommandBuffer &cmd_buf, c
cmd_buf.end_debug_label_region();
}

void RenderGraph::record_command_buffers(const CommandBuffer &cmd_buf, const std::uint32_t img_index) {
void RenderGraph::record_command_buffers(const CommandBuffer &cmd_buf) {
// Transform the image layout of the swapchain (it comes in undefined layout after presenting)
cmd_buf.change_image_layout(m_swapchain.image(img_index), VK_IMAGE_LAYOUT_UNDEFINED,
cmd_buf.change_image_layout(m_swapchain.m_current_img, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);

for (const auto &pass : m_graphics_passes) {
// TODO: Name command buffer on a per-pass basis like [RenderGraph::record_command_buffer|Pass:ImGui]
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,
cmd_buf.change_image_layout(m_swapchain.m_current_img, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
}

void RenderGraph::render() {
const auto &cmd_buf = m_device.request_command_buffer("[RenderGraph::render]");
// TODO: Record command buffers for passes in parallel!
record_command_buffers(cmd_buf, m_swapchain.acquire_next_image_index());
record_command_buffers(cmd_buf);

// TODO: Further abstract this away?
const std::array<VkPipelineStageFlags, 1> stage_mask{VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
Expand Down
Loading

0 comments on commit 24ae683

Please sign in to comment.