Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve synchronization of rendering after changes from transfer queues. #98388

Merged
merged 1 commit into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 35 additions & 7 deletions drivers/vulkan/rendering_device_driver_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2637,11 +2637,13 @@ bool RenderingDeviceDriverVulkan::command_buffer_begin(CommandBufferID p_cmd_buf
bool RenderingDeviceDriverVulkan::command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) {
// Reset is implicit (VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT).

Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);

VkCommandBufferInheritanceInfo inheritance_info = {};
inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
inheritance_info.renderPass = (VkRenderPass)p_render_pass.id;
inheritance_info.subpass = p_subpass;
inheritance_info.framebuffer = (VkFramebuffer)p_framebuffer.id;
inheritance_info.framebuffer = framebuffer->vk_framebuffer;

VkCommandBufferBeginInfo cmd_buf_begin_info = {};
cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Expand Down Expand Up @@ -2951,12 +2953,16 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue,
fb_create_info.height = surface->height;
fb_create_info.layers = 1;

VkFramebuffer framebuffer;
VkFramebuffer vk_framebuffer;
for (uint32_t i = 0; i < image_count; i++) {
fb_create_info.pAttachments = &swap_chain->image_views[i];
err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &framebuffer);
err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer);
ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);

Framebuffer *framebuffer = memnew(Framebuffer);
framebuffer->vk_framebuffer = vk_framebuffer;
framebuffer->swap_chain_image = swap_chain->images[i];
framebuffer->swap_chain_image_subresource_range = view_create_info.subresourceRange;
swap_chain->framebuffers.push_back(RDD::FramebufferID(framebuffer));
}

Expand Down Expand Up @@ -3025,7 +3031,10 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::swap_chain_acquire_framebuffer(C
command_queue->pending_semaphores_for_fence.push_back(semaphore_index);

// Return the corresponding framebuffer to the new current image.
return swap_chain->framebuffers[swap_chain->image_index];
FramebufferID framebuffer_id = swap_chain->framebuffers[swap_chain->image_index];
Framebuffer *framebuffer = (Framebuffer *)(framebuffer_id.id);
framebuffer->swap_chain_acquired = true;
return framebuffer_id;
}

RDD::RenderPassID RenderingDeviceDriverVulkan::swap_chain_get_render_pass(SwapChainID p_swap_chain) {
Expand Down Expand Up @@ -3094,11 +3103,15 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::framebuffer_create(RenderPassID
}
#endif

return FramebufferID(vk_framebuffer);
Framebuffer *framebuffer = memnew(Framebuffer);
framebuffer->vk_framebuffer = vk_framebuffer;
return FramebufferID(framebuffer);
}

void RenderingDeviceDriverVulkan::framebuffer_free(FramebufferID p_framebuffer) {
vkDestroyFramebuffer(vk_device, (VkFramebuffer)p_framebuffer.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER));
Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);
vkDestroyFramebuffer(vk_device, framebuffer->vk_framebuffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER));
memdelete(framebuffer);
}

/****************/
Expand Down Expand Up @@ -4316,10 +4329,25 @@ void RenderingDeviceDriverVulkan::render_pass_free(RenderPassID p_render_pass) {
static_assert(ARRAYS_COMPATIBLE_FIELDWISE(RDD::RenderPassClearValue, VkClearValue));

void RenderingDeviceDriverVulkan::command_begin_render_pass(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, FramebufferID p_framebuffer, CommandBufferType p_cmd_buffer_type, const Rect2i &p_rect, VectorView<RenderPassClearValue> p_clear_values) {
Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);
if (framebuffer->swap_chain_acquired) {
// Insert a barrier to wait for the acquisition of the framebuffer before the render pass begins.
VkImageMemoryBarrier image_barrier = {};
image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
image_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_barrier.image = framebuffer->swap_chain_image;
image_barrier.subresourceRange = framebuffer->swap_chain_image_subresource_range;
vkCmdPipelineBarrier((VkCommandBuffer)p_cmd_buffer.id, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_barrier);
framebuffer->swap_chain_acquired = false;
}

VkRenderPassBeginInfo render_pass_begin = {};
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin.renderPass = (VkRenderPass)p_render_pass.id;
render_pass_begin.framebuffer = (VkFramebuffer)p_framebuffer.id;
render_pass_begin.framebuffer = framebuffer->vk_framebuffer;

render_pass_begin.renderArea.offset.x = p_rect.position.x;
render_pass_begin.renderArea.offset.y = p_rect.position.y;
Expand Down
9 changes: 9 additions & 0 deletions drivers/vulkan/rendering_device_driver_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,15 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
/**** FRAMEBUFFER ****/
/*********************/

struct Framebuffer {
VkFramebuffer vk_framebuffer = VK_NULL_HANDLE;

// Only filled in by a framebuffer created by a swap chain. Unused otherwise.
VkImage swap_chain_image = VK_NULL_HANDLE;
VkImageSubresourceRange swap_chain_image_subresource_range = {};
bool swap_chain_acquired = false;
};

virtual FramebufferID framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height) override final;
virtual void framebuffer_free(FramebufferID p_framebuffer) override final;

Expand Down
18 changes: 15 additions & 3 deletions servers/rendering/rendering_device_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define FORCE_FULL_ACCESS_BITS 0
#define PRINT_RESOURCE_TRACKER_TOTAL 0
#define PRINT_COMMAND_RECORDING 0
#define INSERT_BREADCRUMBS 1

RenderingDeviceGraph::RenderingDeviceGraph() {
driver_honors_barriers = false;
Expand Down Expand Up @@ -438,6 +439,15 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
// Always update the access of the tracker according to the latest usage.
resource_tracker->usage_access = new_usage_access;

// Always accumulate the stages of the tracker with the commands that use it.
search_tracker->current_frame_stages = search_tracker->current_frame_stages | r_command->self_stages;

if (!search_tracker->previous_frame_stages.is_empty()) {
// Add to the command the stages the tracker was used on in the previous frame.
r_command->previous_stages = r_command->previous_stages | search_tracker->previous_frame_stages;
search_tracker->previous_frame_stages.clear();
}

if (different_usage) {
// Even if the usage of the resource isn't a write usage explicitly, a different usage implies a transition and it should therefore be considered a write.
write_usage = true;
Expand Down Expand Up @@ -823,7 +833,7 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC

const RecordedDrawListCommand *draw_list_command = reinterpret_cast<const RecordedDrawListCommand *>(command);
const VectorView clear_values(draw_list_command->clear_values(), draw_list_command->clear_values_count);
#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
#if INSERT_BREADCRUMBS
driver->command_insert_breadcrumb(r_command_buffer, draw_list_command->breadcrumb);
#endif
driver->command_begin_render_pass(r_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values);
Expand Down Expand Up @@ -874,7 +884,7 @@ void RenderingDeviceGraph::_run_label_command_change(RDD::CommandBufferID p_comm
}

if (p_ignore_previous_value || p_new_label_index != r_current_label_index || p_new_level != r_current_label_level) {
if (!p_ignore_previous_value && (p_use_label_for_empty || r_current_label_index >= 0)) {
if (!p_ignore_previous_value && (p_use_label_for_empty || r_current_label_index >= 0 || r_current_label_level >= 0)) {
// End the current label.
driver->command_end_label(p_command_buffer);
}
Expand All @@ -888,6 +898,8 @@ void RenderingDeviceGraph::_run_label_command_change(RDD::CommandBufferID p_comm
} else if (p_use_label_for_empty) {
label_name = "Command graph";
label_color = Color(1, 1, 1, 1);
} else {
return;
}

// Add the level to the name.
Expand Down Expand Up @@ -2064,7 +2076,7 @@ void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RD
}
}

_run_label_command_change(r_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level);
_run_label_command_change(r_command_buffer, -1, -1, false, false, nullptr, 0, current_label_index, current_label_level);

#if PRINT_COMMAND_RECORDING
print_line(vformat("Recorded %d commands", command_count));
Expand Down
5 changes: 4 additions & 1 deletion servers/rendering/rendering_device_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ class RenderingDeviceGraph {
struct ResourceTracker {
uint32_t reference_count = 0;
int64_t command_frame = -1;
BitField<RDD::PipelineStageBits> previous_frame_stages;
BitField<RDD::PipelineStageBits> current_frame_stages;
int32_t read_full_command_list_index = -1;
int32_t read_slice_command_list_index = -1;
int32_t write_command_or_list_index = -1;
Expand All @@ -174,8 +176,9 @@ class RenderingDeviceGraph {

_FORCE_INLINE_ void reset_if_outdated(int64_t new_command_frame) {
if (new_command_frame != command_frame) {
usage_access.clear();
command_frame = new_command_frame;
previous_frame_stages = current_frame_stages;
current_frame_stages.clear();
read_full_command_list_index = -1;
read_slice_command_list_index = -1;
write_command_or_list_index = -1;
Expand Down
Loading