VulkanSwapChain: Always allocate cmdbuffers+1 semaphores

This commit is contained in:
Stenzek 2024-05-25 13:32:57 +10:00
parent e6d8f0d4a0
commit 0f536b8680
No known key found for this signature in database
2 changed files with 17 additions and 13 deletions

View File

@ -22,6 +22,8 @@
Log_SetChannel(VulkanDevice); Log_SetChannel(VulkanDevice);
static_assert(VulkanSwapChain::NUM_SEMAPHORES == (VulkanDevice::NUM_COMMAND_BUFFERS + 1));
static VkFormat GetLinearFormat(VkFormat format) static VkFormat GetLinearFormat(VkFormat format)
{ {
switch (format) switch (format)
@ -541,15 +543,10 @@ bool VulkanSwapChain::CreateSwapChain()
m_images.push_back(image); m_images.push_back(image);
} }
// We don't actually need +1 semaphores, or, more than one really.
// But, the validation layer gets cranky if we don't fence wait before the next image acquire.
// So, add an additional semaphore to ensure that we're never acquiring before fence waiting.
const u32 semaphore_count = image_count + 1;
m_semaphores.reserve(semaphore_count);
m_current_semaphore = 0; m_current_semaphore = 0;
for (u32 i = 0; i < semaphore_count; i++) for (u32 i = 0; i < NUM_SEMAPHORES; i++)
{ {
ImageSemaphores sema; ImageSemaphores& sema = m_semaphores[i];
const VkSemaphoreCreateInfo semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0}; const VkSemaphoreCreateInfo semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0};
res = vkCreateSemaphore(dev.GetVulkanDevice(), &semaphore_info, nullptr, &sema.available_semaphore); res = vkCreateSemaphore(dev.GetVulkanDevice(), &semaphore_info, nullptr, &sema.available_semaphore);
@ -564,10 +561,9 @@ bool VulkanSwapChain::CreateSwapChain()
{ {
LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: "); LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: ");
vkDestroySemaphore(dev.GetVulkanDevice(), sema.available_semaphore, nullptr); vkDestroySemaphore(dev.GetVulkanDevice(), sema.available_semaphore, nullptr);
sema.available_semaphore = VK_NULL_HANDLE;
return false; return false;
} }
m_semaphores.push_back(sema);
} }
return true; return true;
@ -585,10 +581,12 @@ void VulkanSwapChain::DestroySwapChainImages()
m_images.clear(); m_images.clear();
for (auto& it : m_semaphores) for (auto& it : m_semaphores)
{ {
if (it.rendering_finished_semaphore != VK_NULL_HANDLE)
vkDestroySemaphore(dev.GetVulkanDevice(), it.rendering_finished_semaphore, nullptr); vkDestroySemaphore(dev.GetVulkanDevice(), it.rendering_finished_semaphore, nullptr);
if (it.available_semaphore != VK_NULL_HANDLE)
vkDestroySemaphore(dev.GetVulkanDevice(), it.available_semaphore, nullptr); vkDestroySemaphore(dev.GetVulkanDevice(), it.available_semaphore, nullptr);
} }
m_semaphores.clear(); m_semaphores = {};
m_image_acquire_result.reset(); m_image_acquire_result.reset();
} }

View File

@ -9,6 +9,7 @@
#include "common/types.h" #include "common/types.h"
#include <array>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <vector> #include <vector>
@ -16,6 +17,11 @@
class VulkanSwapChain class VulkanSwapChain
{ {
public: public:
// We don't actually need +1 semaphores, or, more than one really.
// But, the validation layer gets cranky if we don't fence wait before the next image acquire.
// So, add an additional semaphore to ensure that we're never acquiring before fence waiting.
static constexpr u32 NUM_SEMAPHORES = 4; // Should be command buffers + 1
~VulkanSwapChain(); ~VulkanSwapChain();
// Creates a vulkan-renderable surface for the specified window handle. // Creates a vulkan-renderable surface for the specified window handle.
@ -108,7 +114,7 @@ private:
VkSwapchainKHR m_swap_chain = VK_NULL_HANDLE; VkSwapchainKHR m_swap_chain = VK_NULL_HANDLE;
std::vector<Image> m_images; std::vector<Image> m_images;
std::vector<ImageSemaphores> m_semaphores; std::array<ImageSemaphores, NUM_SEMAPHORES> m_semaphores = {};
u32 m_current_image = 0; u32 m_current_image = 0;
u32 m_current_semaphore = 0; u32 m_current_semaphore = 0;