[Vulkan] SwapChain: Wait for previous commands to finish before reusing command buffers

This commit is contained in:
DrChat 2017-12-21 13:31:06 -06:00
parent 56ee88b59d
commit 9c48875a5d
2 changed files with 39 additions and 21 deletions

View File

@ -355,6 +355,19 @@ VkResult VulkanSwapChain::Initialize(VkSurfaceKHR surface) {
buffers_[i].image_layout = VK_IMAGE_LAYOUT_UNDEFINED; 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!"); XELOGVK("Swap chain initialized successfully!");
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -445,14 +458,11 @@ void VulkanSwapChain::Shutdown() {
DestroyBuffer(&buffer); DestroyBuffer(&buffer);
} }
buffers_.clear(); buffers_.clear();
if (image_available_semaphore_) {
vkDestroySemaphore(*device_, image_available_semaphore_, nullptr); VK_SAFE_DESTROY(vkDestroySemaphore, *device_, image_available_semaphore_,
image_available_semaphore_ = nullptr; nullptr);
} VK_SAFE_DESTROY(vkDestroyRenderPass, *device_, render_pass_, nullptr);
if (render_pass_) {
vkDestroyRenderPass(*device_, render_pass_, nullptr);
render_pass_ = nullptr;
}
if (copy_cmd_buffer_) { if (copy_cmd_buffer_) {
vkFreeCommandBuffers(*device_, cmd_pool_, 1, &copy_cmd_buffer_); vkFreeCommandBuffers(*device_, cmd_pool_, 1, &copy_cmd_buffer_);
copy_cmd_buffer_ = nullptr; copy_cmd_buffer_ = nullptr;
@ -461,10 +471,8 @@ void VulkanSwapChain::Shutdown() {
vkFreeCommandBuffers(*device_, cmd_pool_, 1, &render_cmd_buffer_); vkFreeCommandBuffers(*device_, cmd_pool_, 1, &render_cmd_buffer_);
render_cmd_buffer_ = nullptr; render_cmd_buffer_ = nullptr;
} }
if (cmd_pool_) { VK_SAFE_DESTROY(vkDestroyCommandPool, *device_, cmd_pool_, nullptr);
vkDestroyCommandPool(*device_, cmd_pool_, nullptr);
cmd_pool_ = nullptr;
}
if (presentation_queue_) { if (presentation_queue_) {
if (!presentation_queue_mutex_) { if (!presentation_queue_mutex_) {
// We own the queue and need to release it. // We own the queue and need to release it.
@ -474,15 +482,12 @@ void VulkanSwapChain::Shutdown() {
presentation_queue_mutex_ = nullptr; presentation_queue_mutex_ = nullptr;
presentation_queue_family_ = -1; 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. // images_ doesn't need to be cleaned up as the swapchain does it implicitly.
if (handle) { VK_SAFE_DESTROY(vkDestroySwapchainKHR, *device_, handle, nullptr);
vkDestroySwapchainKHR(*device_, handle, nullptr); VK_SAFE_DESTROY(vkDestroySurfaceKHR, *instance_, surface_, nullptr);
handle = nullptr;
}
if (surface_) {
vkDestroySurfaceKHR(*instance_, surface_, nullptr);
surface_ = nullptr;
}
} }
VkResult VulkanSwapChain::Begin() { VkResult VulkanSwapChain::Begin() {
@ -490,6 +495,17 @@ VkResult VulkanSwapChain::Begin() {
VkResult status; 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. // Get the index of the next available swapchain image.
status = status =
vkAcquireNextImageKHR(*device_, handle, 0, image_available_semaphore_, vkAcquireNextImageKHR(*device_, handle, 0, image_available_semaphore_,
@ -735,7 +751,8 @@ VkResult VulkanSwapChain::End() {
if (presentation_queue_mutex_) { if (presentation_queue_mutex_) {
presentation_queue_mutex_->lock(); 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_) { if (presentation_queue_mutex_) {
presentation_queue_mutex_->unlock(); presentation_queue_mutex_->unlock();
} }

View File

@ -79,6 +79,7 @@ class VulkanSwapChain {
VulkanInstance* instance_ = nullptr; VulkanInstance* instance_ = nullptr;
VulkanDevice* device_ = nullptr; VulkanDevice* device_ = nullptr;
VkFence synchronization_fence_ = nullptr;
VkQueue presentation_queue_ = nullptr; VkQueue presentation_queue_ = nullptr;
std::mutex* presentation_queue_mutex_ = nullptr; std::mutex* presentation_queue_mutex_ = nullptr;
uint32_t presentation_queue_family_ = -1; uint32_t presentation_queue_family_ = -1;