1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-06 12:20:30 +00:00

Rework semaphores for presentation to be created per swap chain image to fix validation error.

This commit is contained in:
Dario
2025-05-14 15:20:33 -03:00
parent 428a762e98
commit ad22f65489
2 changed files with 27 additions and 31 deletions

View File

@@ -2683,8 +2683,10 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu
if (p_cmd_buffers.size() > 0) { if (p_cmd_buffers.size() > 0) {
thread_local LocalVector<VkCommandBuffer> command_buffers; thread_local LocalVector<VkCommandBuffer> command_buffers;
thread_local LocalVector<VkSemaphore> present_semaphores;
thread_local LocalVector<VkSemaphore> signal_semaphores; thread_local LocalVector<VkSemaphore> signal_semaphores;
command_buffers.clear(); command_buffers.clear();
present_semaphores.clear();
signal_semaphores.clear(); signal_semaphores.clear();
for (uint32_t i = 0; i < p_cmd_buffers.size(); i++) { for (uint32_t i = 0; i < p_cmd_buffers.size(); i++) {
@@ -2696,27 +2698,11 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu
signal_semaphores.push_back(VkSemaphore(p_cmd_semaphores[i].id)); signal_semaphores.push_back(VkSemaphore(p_cmd_semaphores[i].id));
} }
VkSemaphore present_semaphore = VK_NULL_HANDLE; for (uint32_t i = 0; i < p_swap_chains.size(); i++) {
if (p_swap_chains.size() > 0) { const SwapChain *swap_chain = (const SwapChain *)(p_swap_chains[i].id);
if (command_queue->present_semaphores.is_empty()) { VkSemaphore semaphore = swap_chain->present_semaphores[swap_chain->image_index];
// Create the semaphores used for presentation if they haven't been created yet. present_semaphores.push_back(semaphore);
VkSemaphore semaphore = VK_NULL_HANDLE; signal_semaphores.push_back(semaphore);
VkSemaphoreCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (uint32_t i = 0; i < frame_count; i++) {
err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &semaphore);
ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);
command_queue->present_semaphores.push_back(semaphore);
}
}
// If a presentation semaphore is required, cycle across the ones available on the queue. It is technically possible
// and valid to reuse the same semaphore for this particular operation, but we create multiple ones anyway in case
// some hardware expects multiple semaphores to be used.
present_semaphore = command_queue->present_semaphores[command_queue->present_semaphore_index];
signal_semaphores.push_back(present_semaphore);
command_queue->present_semaphore_index = (command_queue->present_semaphore_index + 1) % command_queue->present_semaphores.size();
} }
VkSubmitInfo submit_info = {}; VkSubmitInfo submit_info = {};
@@ -2750,10 +2736,9 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu
command_queue->pending_semaphores_for_fence.clear(); command_queue->pending_semaphores_for_fence.clear();
} }
if (present_semaphore != VK_NULL_HANDLE) { if (!present_semaphores.is_empty()) {
// If command buffers were executed, swap chains must wait on the present semaphore used by the command queue. // If command buffers were executed, swap chains must wait on the present semaphore used by the command queue.
wait_semaphores.clear(); wait_semaphores = present_semaphores;
wait_semaphores.push_back(present_semaphore);
} }
} }
@@ -2838,11 +2823,6 @@ void RenderingDeviceDriverVulkan::command_queue_free(CommandQueueID p_cmd_queue)
CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id); CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);
// Erase all the semaphores used for presentation.
for (VkSemaphore semaphore : command_queue->present_semaphores) {
vkDestroySemaphore(vk_device, semaphore, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));
}
// Erase all the semaphores used for image acquisition. // Erase all the semaphores used for image acquisition.
for (VkSemaphore semaphore : command_queue->image_semaphores) { for (VkSemaphore semaphore : command_queue->image_semaphores) {
vkDestroySemaphore(vk_device, semaphore, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE)); vkDestroySemaphore(vk_device, semaphore, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));
@@ -3024,6 +3004,12 @@ void RenderingDeviceDriverVulkan::_swap_chain_release(SwapChain *swap_chain) {
swap_chain->command_queues_acquired.clear(); swap_chain->command_queues_acquired.clear();
swap_chain->command_queues_acquired_semaphores.clear(); swap_chain->command_queues_acquired_semaphores.clear();
for (VkSemaphore semaphore : swap_chain->present_semaphores) {
vkDestroySemaphore(vk_device, semaphore, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE));
}
swap_chain->present_semaphores.clear();
} }
RenderingDeviceDriver::SwapChainID RenderingDeviceDriverVulkan::swap_chain_create(RenderingContextDriver::SurfaceID p_surface) { RenderingDeviceDriver::SwapChainID RenderingDeviceDriverVulkan::swap_chain_create(RenderingContextDriver::SurfaceID p_surface) {
@@ -3360,6 +3346,17 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue,
swap_chain->framebuffers.push_back(RDD::FramebufferID(framebuffer)); swap_chain->framebuffers.push_back(RDD::FramebufferID(framebuffer));
} }
VkSemaphore vk_semaphore = VK_NULL_HANDLE;
for (uint32_t i = 0; i < image_count; i++) {
VkSemaphoreCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
err = vkCreateSemaphore(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_SEMAPHORE), &vk_semaphore);
ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);
swap_chain->present_semaphores.push_back(vk_semaphore);
}
// Once everything's been created correctly, indicate the surface no longer needs to be resized. // Once everything's been created correctly, indicate the surface no longer needs to be resized.
context_driver->surface_set_needs_resize(swap_chain->surface, false); context_driver->surface_set_needs_resize(swap_chain->surface, false);

View File

@@ -302,7 +302,6 @@ public:
// ----- QUEUE ----- // ----- QUEUE -----
private: private:
struct CommandQueue { struct CommandQueue {
LocalVector<VkSemaphore> present_semaphores;
LocalVector<VkSemaphore> image_semaphores; LocalVector<VkSemaphore> image_semaphores;
LocalVector<SwapChain *> image_semaphores_swap_chains; LocalVector<SwapChain *> image_semaphores_swap_chains;
LocalVector<uint32_t> pending_semaphores_for_execute; LocalVector<uint32_t> pending_semaphores_for_execute;
@@ -311,7 +310,6 @@ private:
LocalVector<Pair<Fence *, uint32_t>> image_semaphores_for_fences; LocalVector<Pair<Fence *, uint32_t>> image_semaphores_for_fences;
uint32_t queue_family = 0; uint32_t queue_family = 0;
uint32_t queue_index = 0; uint32_t queue_index = 0;
uint32_t present_semaphore_index = 0;
}; };
public: public:
@@ -361,6 +359,7 @@ private:
VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
TightLocalVector<VkImage> images; TightLocalVector<VkImage> images;
TightLocalVector<VkImageView> image_views; TightLocalVector<VkImageView> image_views;
TightLocalVector<VkSemaphore> present_semaphores;
TightLocalVector<FramebufferID> framebuffers; TightLocalVector<FramebufferID> framebuffers;
LocalVector<CommandQueue *> command_queues_acquired; LocalVector<CommandQueue *> command_queues_acquired;
LocalVector<uint32_t> command_queues_acquired_semaphores; LocalVector<uint32_t> command_queues_acquired_semaphores;