diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp index 4707180c1e0..72b1881aea8 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp @@ -2683,8 +2683,10 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu if (p_cmd_buffers.size() > 0) { thread_local LocalVector command_buffers; + thread_local LocalVector present_semaphores; thread_local LocalVector signal_semaphores; command_buffers.clear(); + present_semaphores.clear(); signal_semaphores.clear(); 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)); } - VkSemaphore present_semaphore = VK_NULL_HANDLE; - if (p_swap_chains.size() > 0) { - if (command_queue->present_semaphores.is_empty()) { - // Create the semaphores used for presentation if they haven't been created yet. - VkSemaphore semaphore = VK_NULL_HANDLE; - 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(); + for (uint32_t i = 0; i < p_swap_chains.size(); i++) { + const SwapChain *swap_chain = (const SwapChain *)(p_swap_chains[i].id); + VkSemaphore semaphore = swap_chain->present_semaphores[swap_chain->image_index]; + present_semaphores.push_back(semaphore); + signal_semaphores.push_back(semaphore); } VkSubmitInfo submit_info = {}; @@ -2750,10 +2736,9 @@ Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueu 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. - wait_semaphores.clear(); - wait_semaphores.push_back(present_semaphore); + wait_semaphores = present_semaphores; } } @@ -2838,11 +2823,6 @@ void RenderingDeviceDriverVulkan::command_queue_free(CommandQueueID p_cmd_queue) 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. for (VkSemaphore semaphore : command_queue->image_semaphores) { 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_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) { @@ -3360,6 +3346,17 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, 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. context_driver->surface_set_needs_resize(swap_chain->surface, false); diff --git a/drivers/vulkan/rendering_device_driver_vulkan.h b/drivers/vulkan/rendering_device_driver_vulkan.h index c25acd64d89..07c1b2a0a9b 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.h +++ b/drivers/vulkan/rendering_device_driver_vulkan.h @@ -302,7 +302,6 @@ public: // ----- QUEUE ----- private: struct CommandQueue { - LocalVector present_semaphores; LocalVector image_semaphores; LocalVector image_semaphores_swap_chains; LocalVector pending_semaphores_for_execute; @@ -311,7 +310,6 @@ private: LocalVector> image_semaphores_for_fences; uint32_t queue_family = 0; uint32_t queue_index = 0; - uint32_t present_semaphore_index = 0; }; public: @@ -361,6 +359,7 @@ private: VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; TightLocalVector images; TightLocalVector image_views; + TightLocalVector present_semaphores; TightLocalVector framebuffers; LocalVector command_queues_acquired; LocalVector command_queues_acquired_semaphores;