From 9c48875a5d755a7b5055bfd00d581d3921b1838b Mon Sep 17 00:00:00 2001 From: DrChat Date: Thu, 21 Dec 2017 13:31:06 -0600 Subject: [PATCH] [Vulkan] SwapChain: Wait for previous commands to finish before reusing command buffers --- src/xenia/ui/vulkan/vulkan_swap_chain.cc | 59 +++++++++++++++--------- src/xenia/ui/vulkan/vulkan_swap_chain.h | 1 + 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/xenia/ui/vulkan/vulkan_swap_chain.cc b/src/xenia/ui/vulkan/vulkan_swap_chain.cc index cd792e743..38c19852e 100644 --- a/src/xenia/ui/vulkan/vulkan_swap_chain.cc +++ b/src/xenia/ui/vulkan/vulkan_swap_chain.cc @@ -355,6 +355,19 @@ VkResult VulkanSwapChain::Initialize(VkSurfaceKHR surface) { buffers_[i].image_layout = VK_IMAGE_LAYOUT_UNDEFINED; } + // Create a fence we'll use to wait for commands to finish. + VkFenceCreateInfo fence_create_info = { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + nullptr, + VK_FENCE_CREATE_SIGNALED_BIT, + }; + status = vkCreateFence(*device_, &fence_create_info, nullptr, + &synchronization_fence_); + CheckResult(status, "vkGetSwapchainImagesKHR"); + if (status != VK_SUCCESS) { + return status; + } + XELOGVK("Swap chain initialized successfully!"); return VK_SUCCESS; } @@ -445,14 +458,11 @@ void VulkanSwapChain::Shutdown() { DestroyBuffer(&buffer); } buffers_.clear(); - if (image_available_semaphore_) { - vkDestroySemaphore(*device_, image_available_semaphore_, nullptr); - image_available_semaphore_ = nullptr; - } - if (render_pass_) { - vkDestroyRenderPass(*device_, render_pass_, nullptr); - render_pass_ = nullptr; - } + + VK_SAFE_DESTROY(vkDestroySemaphore, *device_, image_available_semaphore_, + nullptr); + VK_SAFE_DESTROY(vkDestroyRenderPass, *device_, render_pass_, nullptr); + if (copy_cmd_buffer_) { vkFreeCommandBuffers(*device_, cmd_pool_, 1, ©_cmd_buffer_); copy_cmd_buffer_ = nullptr; @@ -461,10 +471,8 @@ void VulkanSwapChain::Shutdown() { vkFreeCommandBuffers(*device_, cmd_pool_, 1, &render_cmd_buffer_); render_cmd_buffer_ = nullptr; } - if (cmd_pool_) { - vkDestroyCommandPool(*device_, cmd_pool_, nullptr); - cmd_pool_ = nullptr; - } + VK_SAFE_DESTROY(vkDestroyCommandPool, *device_, cmd_pool_, nullptr); + if (presentation_queue_) { if (!presentation_queue_mutex_) { // We own the queue and need to release it. @@ -474,15 +482,12 @@ void VulkanSwapChain::Shutdown() { presentation_queue_mutex_ = nullptr; presentation_queue_family_ = -1; } + + VK_SAFE_DESTROY(vkDestroyFence, *device_, synchronization_fence_, nullptr); + // images_ doesn't need to be cleaned up as the swapchain does it implicitly. - if (handle) { - vkDestroySwapchainKHR(*device_, handle, nullptr); - handle = nullptr; - } - if (surface_) { - vkDestroySurfaceKHR(*instance_, surface_, nullptr); - surface_ = nullptr; - } + VK_SAFE_DESTROY(vkDestroySwapchainKHR, *device_, handle, nullptr); + VK_SAFE_DESTROY(vkDestroySurfaceKHR, *instance_, surface_, nullptr); } VkResult VulkanSwapChain::Begin() { @@ -490,6 +495,17 @@ VkResult VulkanSwapChain::Begin() { VkResult status; + // Wait for the last swap to finish. + status = vkWaitForFences(*device_, 1, &synchronization_fence_, VK_TRUE, -1); + if (status != VK_SUCCESS) { + return status; + } + + status = vkResetFences(*device_, 1, &synchronization_fence_); + if (status != VK_SUCCESS) { + return status; + } + // Get the index of the next available swapchain image. status = vkAcquireNextImageKHR(*device_, handle, 0, image_available_semaphore_, @@ -735,7 +751,8 @@ VkResult VulkanSwapChain::End() { if (presentation_queue_mutex_) { presentation_queue_mutex_->lock(); } - status = vkQueueSubmit(presentation_queue_, 1, &render_submit_info, nullptr); + status = vkQueueSubmit(presentation_queue_, 1, &render_submit_info, + synchronization_fence_); if (presentation_queue_mutex_) { presentation_queue_mutex_->unlock(); } diff --git a/src/xenia/ui/vulkan/vulkan_swap_chain.h b/src/xenia/ui/vulkan/vulkan_swap_chain.h index 1c070803c..14475536b 100644 --- a/src/xenia/ui/vulkan/vulkan_swap_chain.h +++ b/src/xenia/ui/vulkan/vulkan_swap_chain.h @@ -79,6 +79,7 @@ class VulkanSwapChain { VulkanInstance* instance_ = nullptr; VulkanDevice* device_ = nullptr; + VkFence synchronization_fence_ = nullptr; VkQueue presentation_queue_ = nullptr; std::mutex* presentation_queue_mutex_ = nullptr; uint32_t presentation_queue_family_ = -1;