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 20, 2024
1 parent 0d13451 commit 6ec3597
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 56 deletions.
12 changes: 6 additions & 6 deletions include/inexor/vulkan-renderer/render-graph/render_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,16 +251,16 @@ class RenderGraph {
/// Create the graphics pipelines
void create_graphics_pipelines();

/// Create the textures
void create_textures();

/// Determine the order of execution of the graphics passes by using depth first search (DFS) algorithm
void determine_pass_order();

/// Fill the VkRenderingInfo for a graphics pass
/// @param pass The graphics pass
void fill_graphics_pass_rendering_info(GraphicsPass &pass);

/// Call m_on_initialize for every texture
void initialize_textures();

/// Record the command buffer of a pass. After a lot of discussions about the API design of rendergraph, we came to
/// the conclusion that it's the full responsibility of the programmer to manually bind pipelines, descriptors sets,
/// and buffers inside of the on_record function instead of attempting to abstract all of this in rendergraph. This
Expand All @@ -280,13 +280,13 @@ class RenderGraph {
/// @note If a uniform buffer has been updated, an update of the associated descriptor set will be performed
void update_buffers();

/// Update dynamic textures
void update_textures();

/// Update the write descriptor sets
/// @note This function must only be called once during rendergraph compilation, not for every frame!
void update_write_descriptor_sets();

/// Update dynamic textures
void update_textures();

/// Make sure all required resources are specified so rendergraph is ready to be compiled
void validate_render_graph();

Expand Down
11 changes: 11 additions & 0 deletions include/inexor/vulkan-renderer/render-graph/texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ class Texture {
Texture &operator=(const Texture &) = delete;
Texture &operator=(Texture &&) = delete;

[[nodiscard]] VkFormat format() const {
return m_format;
}

[[nodiscard]] VkExtent2D extent() const {
return {
.width = m_width,
.height = m_height,
};
}

/// Request rendergraph to update the texture
/// @param src_texture_data A pointer to the source data
/// @param src_texture_data_size The size of the source data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ class CommandBuffer {
/// @param first_inst The instance ID of the first instance to draw (``0`` by default)
/// @return A const reference to the this pointer (allowing method calls to be chained)
const CommandBuffer &draw(std::uint32_t vert_count,
std::uint32_t inst_count = 1, // NOLINT
std::uint32_t inst_count = 1,
std::uint32_t first_vert = 0,
std::uint32_t first_inst = 0) const;

Expand All @@ -237,7 +237,7 @@ class CommandBuffer {
/// @param index_count The number of indices to draw
/// @return A const reference to the this pointer (allowing method calls to be chained)
const CommandBuffer &draw_indexed(std::uint32_t index_count,
std::uint32_t inst_count = 1, // NOLINT
std::uint32_t inst_count = 1,
std::uint32_t first_index = 0,
std::int32_t vert_offset = 0,
std::uint32_t first_inst = 0) const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,17 @@ class WriteDescriptorSetBuilder {

/// Add a write descriptor set for a uniform buffer
/// @param descriptor_set The destination descriptor set
/// @param buffer The rendergraph uniform buffer
/// @param uniform_buffer The rendergraph uniform buffer
/// @return A reference to the dereferenced ``this`` pointer
WriteDescriptorSetBuilder &add_uniform_buffer_update(VkDescriptorSet descriptor_set, std::weak_ptr<Buffer> buffer);
WriteDescriptorSetBuilder &add_uniform_buffer_update(VkDescriptorSet descriptor_set,
std::weak_ptr<Buffer> uniform_buffer);

/// Add a write descriptor set for a combined image sampler
/// @param descriptor_set The destination descriptor set
/// @param texture The rendergraph texture
/// @param texture_image The rendergraph texture
/// @return A reference to the dereferenced ``this`` pointer
WriteDescriptorSetBuilder &add_combined_image_sampler_update(VkDescriptorSet descriptor_set,
std::weak_ptr<Texture> texture);
std::weak_ptr<Texture> texture_image);
/// Return the write descriptor sets and reset the builder
/// @return A std::vector of VkWriteDescriptorSet
[[nodiscard]] std::vector<VkWriteDescriptorSet> build();
Expand Down
5 changes: 3 additions & 2 deletions src/vulkan-renderer/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,9 @@ void Application::setup_render_graph() {

// TODO: We don't need to recreate the imgui overlay when swapchain is recreated, use a .recreate() method instead?
// TODO: Decouple ImGuiRenderer form ImGuiLoader
m_imgui_overlay = std::make_unique<renderers::ImGuiRenderer>(*m_device, m_render_graph, m_octree_pass, m_swapchain,
[&]() { update_imgui_overlay(); });
// m_imgui_overlay = std::make_unique<renderers::ImGuiRenderer>(*m_device, m_render_graph, m_octree_pass,
// m_swapchain,
// [&]() { update_imgui_overlay(); });

m_render_graph->compile();
}
Expand Down
2 changes: 2 additions & 0 deletions src/vulkan-renderer/render-graph/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ void Buffer::create(const CommandBuffer &cmd_buf) {
};
// The update is finished
m_update_requested = false;
m_src_data = nullptr;
m_src_data_size = 0;

// NOTE: The staging buffer needs to stay valid until command buffer finished executing!
// It will be destroyed either in the destructor or the next time create is called.
Expand Down
2 changes: 1 addition & 1 deletion src/vulkan-renderer/render-graph/graphics_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ GraphicsPass::GraphicsPass(
.height = attachment->m_height,
};
} else if (!write_swapchains.empty()) {
// No color attachments, so pick the extent from any of the swapchains specified
const auto &swapchain = write_swapchains[0].first.lock();
m_extent = swapchain->m_extent;
}

// Check if either width or height is 0
if (m_extent.width == 0) {
throw std::runtime_error("[GraphicsPass::GraphicsPass] Error: m_extent.width is 0!");
Expand Down
64 changes: 34 additions & 30 deletions src/vulkan-renderer/render-graph/render_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ void RenderGraph::compile() {
validate_render_graph();
determine_pass_order();
update_buffers();
create_textures();
initialize_textures();
update_textures();
create_descriptor_set_layouts();
allocate_descriptor_sets();
update_write_descriptor_sets();
create_graphics_passes();
create_graphics_pipelines();
collect_swapchain_image_available_semaphores();
Expand Down Expand Up @@ -141,26 +141,6 @@ void RenderGraph::create_graphics_pipelines() {
}
}

void RenderGraph::create_textures() {
m_device.execute("[RenderGraph::create_textures]", VK_QUEUE_GRAPHICS_BIT, DebugLabelColor::BLUE,
[&](const CommandBuffer &cmd_buf) {
for (const auto &texture : m_textures) {
if (texture->m_on_init) {
cmd_buf.set_suboperation_debug_name("[Texture|Initialize]:" + texture->m_name + "]");
std::invoke(texture->m_on_init.value());
}
cmd_buf.set_suboperation_debug_name("[Texture|Create]:" + texture->m_name + "]");
texture->create();
if (texture->m_usage == TextureUsage::NORMAL) {
cmd_buf.set_suboperation_debug_name("[Texture|Update]:" + texture->m_name + "]");
// Only external textures are updated, not back or depth buffers used internally in
// rendergraph
texture->update(cmd_buf);
}
}
});
}

void RenderGraph::determine_pass_order() {
m_log->warn("Implement determine_pass_order()");
// TODO: The data structure to determine pass order should be created before rendergraph compilation!
Expand Down Expand Up @@ -270,6 +250,37 @@ void RenderGraph::fill_graphics_pass_rendering_info(GraphicsPass &pass) {
});
}

// TODO: Consistent naming: create, initialize, update=create for static textures...?

void RenderGraph::initialize_textures() {
// Check if there is any update required
bool any_update_required = false;
for (const auto &texture : m_textures) {
// NOTE: For textures which are created internally by rendergraph, m_on_init is std::nullopt
if (texture->m_on_init) {
std::invoke(texture->m_on_init.value());
if (texture->m_update_requested) {
any_update_required = true;
}
}
}
// Only start recording and submitting a command buffer on transfer queue if any update is required
if (any_update_required) {
m_device.execute("[RenderGraph::initialize_textures]", VK_QUEUE_TRANSFER_BIT, DebugLabelColor::LIME,
[&](const CommandBuffer &cmd_buf) {
for (const auto &texture : m_textures) {
if (texture->m_update_requested) {
cmd_buf.set_suboperation_debug_name("[Texture|Create:" + texture->m_name + "]");
texture->create();
texture->update(cmd_buf);
}
}
});
}
// NOTE: For the "else" case: We can't insert a debug label here telling us that there are no buffer updates
// required because that command itself would require a command buffer to be in recording state
}

void RenderGraph::record_command_buffer_for_pass(const CommandBuffer &cmd_buf, GraphicsPass &pass) {
cmd_buf.set_suboperation_debug_name("[Pass:" + pass.m_name + "]");
// Start a new debug label for this graphics pass (visible in graphics debuggers like RenderDoc)
Expand Down Expand Up @@ -307,9 +318,7 @@ void RenderGraph::record_command_buffer_for_pass(const CommandBuffer &cmd_buf, G
if (!pass.m_next_pass.expired()) {
const auto &next_pass = pass.m_next_pass.lock();
for (const auto &next_pass_write_swapchain : next_pass->m_write_swapchains) {
const auto swapchain_1 = next_pass_write_swapchain.first;
const auto swapchain_2 = swapchain.first;
if (swapchain_1.lock() == swapchain_2.lock()) {
if (next_pass_write_swapchain.first.lock() == swapchain.first.lock()) {
next_pass_writes_to_this_swapchain = true;
}
}
Expand All @@ -329,12 +338,7 @@ void RenderGraph::render() {
update_buffers();
update_textures();
update_write_descriptor_sets();
// NOTE: We only need to call update_write_descriptor_sets() once in rendergraph compilation, not every frame!

// TODO: Only wait for img_available on first use of a swapchain!

// So if we are writing to multiple swapchains in this pass, we must wait for every swapchains
// semaphore!
m_device.execute(
"[RenderGraph::render]", VK_QUEUE_GRAPHICS_BIT, DebugLabelColor::CYAN,
[&](const CommandBuffer &cmd_buf) {
Expand Down
7 changes: 7 additions & 0 deletions src/vulkan-renderer/render-graph/texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,17 @@ void Texture::update(const CommandBuffer &cmd_buf) {
throw VulkanException("Error: vmaCreateBuffer failed for staging buffer " + m_name + "!", result);
}

// Copy the texture data into the staging buffer
std::memcpy(m_staging_buffer_alloc_info.pMappedData, m_src_texture_data, m_src_texture_data_size);

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

cmd_buf.insert_debug_label("[Texture::update|" + m_name + "]",
wrapper::get_debug_label_color(wrapper::DebugLabelColor::ORANGE));
cmd_buf.pipeline_image_memory_barrier_before_copy_buffer_to_image(m_img->m_img)
.copy_buffer_to_image(m_staging_buffer, m_img->m_img,
{
Expand All @@ -172,6 +177,8 @@ void Texture::update(const CommandBuffer &cmd_buf) {

// The update is finished
m_update_requested = false;
m_src_texture_data = nullptr;
m_src_texture_data_size = 0;

// NOTE: The staging buffer needs to stay valid until command buffer finished executing!
// It will be destroyed either in the destructor or the next time execute_update is called.
Expand Down
10 changes: 8 additions & 2 deletions src/vulkan-renderer/wrapper/commands/command_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,10 @@ const CommandBuffer &CommandBuffer::pipeline_image_memory_barrier(const VkPipeli
}

const CommandBuffer &CommandBuffer::pipeline_image_memory_barrier_after_copy_buffer_to_image(const VkImage img) const {
assert(img);
if (!img) {
throw std::invalid_argument("[CommandBuffer::pipeline_image_memory_barrier_after_copy_buffer_to_image] Error: "
"Parameter 'img' is an invalid pointer!");
}
return pipeline_image_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, // src_stage_flags
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dst_stage_flags
VK_ACCESS_TRANSFER_WRITE_BIT, // src_access_flags
Expand All @@ -367,7 +370,10 @@ const CommandBuffer &CommandBuffer::pipeline_image_memory_barrier_after_copy_buf
}

const CommandBuffer &CommandBuffer::pipeline_image_memory_barrier_before_copy_buffer_to_image(const VkImage img) const {
assert(img);
if (!img) {
throw std::invalid_argument("[CommandBuffer::pipeline_image_memory_barrier_before_copy_buffer_to_image] Error: "
"Parameter 'img' is an invalid pointer!");
}
return pipeline_image_memory_barrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // src_stage_flags
VK_PIPELINE_STAGE_TRANSFER_BIT, // dst_stage_flags
0, // src_access_flags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,69 @@ WriteDescriptorSetBuilder::WriteDescriptorSetBuilder(WriteDescriptorSetBuilder &
// TODO: Implement me!
}

WriteDescriptorSetBuilder &WriteDescriptorSetBuilder::add_uniform_buffer_update(const VkDescriptorSet descriptor_set,
const std::weak_ptr<Buffer> buffer) {
assert(descriptor_set);
if (buffer.lock()->m_buffer_type != BufferType::UNIFORM_BUFFER) {
WriteDescriptorSetBuilder &
WriteDescriptorSetBuilder::add_uniform_buffer_update(const VkDescriptorSet descriptor_set,
const std::weak_ptr<Buffer> uniform_buffer) {

if (!descriptor_set) {
throw std::invalid_argument("[WriteDescriptorSetBuilder::add_uniform_buffer_update] Error: Parameter "
"'descriptor_set' is invalid!");
}
if (uniform_buffer.lock()->m_buffer_type != BufferType::UNIFORM_BUFFER) {
throw std::invalid_argument("[DescriptorSetUpdateBuilder::add_uniform_buffer_update] Error: Buffer " +
buffer.lock()->m_name + " is not a uniform buffer!");
uniform_buffer.lock()->m_name + " is not a uniform buffer!");
}
const auto &buffer = uniform_buffer.lock();
if (!buffer->m_descriptor_buffer_info.buffer) {
throw std::invalid_argument("[WriteDescriptorSetBuilder::add_uniform_buffer_update] Error: "
"Buffer::m_descriptor_buffer_info.buffer' of uniform buffer '" +
buffer->m_name + "' is invalid!");
}
m_write_descriptor_sets.emplace_back(wrapper::make_info<VkWriteDescriptorSet>({
.dstSet = descriptor_set,
.dstBinding = m_binding,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pBufferInfo = &buffer.lock()->m_descriptor_buffer_info,
.pBufferInfo = &buffer->m_descriptor_buffer_info,
}));

m_binding++;
return *this;
}

WriteDescriptorSetBuilder &
WriteDescriptorSetBuilder::add_combined_image_sampler_update(const VkDescriptorSet descriptor_set,
const std::weak_ptr<Texture> texture) {
assert(descriptor_set);
const std::weak_ptr<Texture> image_texture) {
if (!descriptor_set) {
throw std::invalid_argument("[WriteDescriptorSetBuilder::add_combined_image_sampler_update] Error: Parameter "
"'descriptor_set' is invalid!");
}
if (image_texture.expired()) {
throw std::invalid_argument(
"[WriteDescriptorSetBuilder::add_combined_image_sampler_update] Error: Parameter 'texture' is invalid!");
}

const auto &texture = image_texture.lock();
if (!texture->m_descriptor_img_info.imageView) {
throw std::invalid_argument("[WriteDescriptorSetBuilder::add_combined_image_sampler_update] Error: "
"'Texture::m_descriptor_img_info.imageView' of texture '" +
texture->m_name + "' is invalid!");
}
if (!texture->m_descriptor_img_info.sampler) {
throw std::invalid_argument("[WriteDescriptorSetBuilder::add_combined_image_sampler_update] Error: "
"'Texture::m_descriptor_img_info.sampler' of texture '" +
texture->m_name + "' is invalid!");
}
m_write_descriptor_sets.emplace_back(wrapper::make_info<VkWriteDescriptorSet>({
.dstSet = descriptor_set,
.dstBinding = m_binding,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &texture.lock()->m_descriptor_img_info,
.pImageInfo = &texture->m_descriptor_img_info,
}));

m_binding++;
return *this;
}
Expand Down
1 change: 1 addition & 0 deletions src/vulkan-renderer/wrapper/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ std::uint32_t device_type_rating(const DeviceInfo &info) {
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
return 1;
default:
// This means we ignore any other gpu types by default
return 0;
}
}
Expand Down

0 comments on commit 6ec3597

Please sign in to comment.