Skip to content

Commit

Permalink
GS/Vulkan: Work around validation layer semaphore error
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed May 25, 2024
1 parent c7a21a6 commit 3928014
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 15 deletions.
22 changes: 10 additions & 12 deletions pcsx2/GS/Renderers/Vulkan/VKSwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <X11/Xlib.h>
#endif

static_assert(VKSwapChain::NUM_SEMAPHORES == (GSDeviceVK::NUM_COMMAND_BUFFERS + 1));

VKSwapChain::VKSwapChain(const WindowInfo& wi, VkSurfaceKHR surface, VkPresentModeKHR present_mode,
std::optional<bool> exclusive_fullscreen_control)
: m_window_info(wi)
Expand Down Expand Up @@ -455,15 +457,10 @@ bool VKSwapChain::CreateSwapChain()
m_images.push_back(std::move(texture));
}

// 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;
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};
res = vkCreateSemaphore(
Expand All @@ -480,10 +477,9 @@ bool VKSwapChain::CreateSwapChain()
{
LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: ");
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), sema.available_semaphore, nullptr);
sema.available_semaphore = VK_NULL_HANDLE;
return false;
}

m_semaphores.push_back(sema);
}

return true;
Expand All @@ -499,10 +495,12 @@ void VKSwapChain::DestroySwapChainImages()
m_images.clear();
for (auto& it : m_semaphores)
{
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), it.rendering_finished_semaphore, nullptr);
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), it.available_semaphore, nullptr);
if (it.rendering_finished_semaphore != VK_NULL_HANDLE)
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), it.rendering_finished_semaphore, nullptr);
if (it.available_semaphore != VK_NULL_HANDLE)
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), it.available_semaphore, nullptr);
}
m_semaphores.clear();
m_semaphores = {};

m_image_acquire_result.reset();
}
Expand Down
10 changes: 7 additions & 3 deletions pcsx2/GS/Renderers/Vulkan/VKSwapChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@

#include "common/WindowInfo.h"

#include <array>
#include <memory>
#include <optional>
#include <vector>

class VKSwapChain
{
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

~VKSwapChain();

// Creates a vulkan-renderable surface for the specified window handle.
Expand Down Expand Up @@ -81,8 +87,6 @@ class VKSwapChain

bool CreateSwapChain();
void DestroySwapChain();

bool SetupSwapChainImages(VkFormat image_format);
void DestroySwapChainImages();

void DestroySurface();
Expand All @@ -99,7 +103,7 @@ class VKSwapChain
VkSwapchainKHR m_swap_chain = VK_NULL_HANDLE;

std::vector<std::unique_ptr<GSTextureVK>> m_images;
std::vector<ImageSemaphores> m_semaphores;
std::array<ImageSemaphores, NUM_SEMAPHORES> m_semaphores = {};

u32 m_current_image = 0;
u32 m_current_semaphore = 0;
Expand Down

0 comments on commit 3928014

Please sign in to comment.