Merge pull request #98388 from DarioSamo/sync-fixes
Improve synchronization of rendering after changes from transfer queues.
This commit is contained in:
commit
a14e9e99e5
4 changed files with 63 additions and 11 deletions
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/****************/
|
||||
|
@ -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;
|
||||
|
|
|
@ -366,6 +366,15 @@ public:
|
|||
/**** 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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
|
|
@ -151,6 +151,8 @@ public:
|
|||
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;
|
||||
|
@ -174,8 +176,9 @@ public:
|
|||
|
||||
_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;
|
||||
|
|
Loading…
Reference in a new issue