Vulkan: Fix freeze when closing pad view (#435)

This commit is contained in:
goeiecool9999 2022-11-06 00:40:00 +01:00 committed by GitHub
parent 948460cad7
commit 138510106c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 36 deletions

View File

@ -676,6 +676,12 @@ SwapchainInfoVk& VulkanRenderer::GetChainInfo(bool mainWindow) const
return *GetChainInfoPtr(mainWindow); return *GetChainInfoPtr(mainWindow);
} }
void VulkanRenderer::StopUsingPadAndWait()
{
m_destroyPadSwapchainNextAcquire = true;
m_padCloseReadySemaphore.wait();
}
bool VulkanRenderer::IsPadWindowActive() bool VulkanRenderer::IsPadWindowActive()
{ {
return IsSwapchainInfoValid(false); return IsSwapchainInfoValid(false);
@ -1658,15 +1664,12 @@ bool VulkanRenderer::ImguiBegin(bool mainWindow)
auto& chainInfo = GetChainInfo(mainWindow); auto& chainInfo = GetChainInfo(mainWindow);
if (!IsSwapchainInfoValid(mainWindow)) if (!AcquireNextSwapchainImage(mainWindow))
return false; return false;
draw_endRenderPass(); draw_endRenderPass();
m_state.currentPipeline = VK_NULL_HANDLE; m_state.currentPipeline = VK_NULL_HANDLE;
AcquireNextSwapchainImage(mainWindow);
ImGui_ImplVulkan_CreateFontsTexture(m_state.currentCommandBuffer); ImGui_ImplVulkan_CreateFontsTexture(m_state.currentCommandBuffer);
ImGui_ImplVulkan_NewFrame(m_state.currentCommandBuffer, chainInfo.m_swapchainFramebuffers[chainInfo.swapchainImageIndex], chainInfo.swapchainExtent); ImGui_ImplVulkan_NewFrame(m_state.currentCommandBuffer, chainInfo.m_swapchainFramebuffers[chainInfo.swapchainImageIndex], chainInfo.swapchainExtent);
ImGui_UpdateWindowInformation(mainWindow); ImGui_UpdateWindowInformation(mainWindow);
@ -1718,11 +1721,9 @@ void VulkanRenderer::DeleteFontTextures()
bool VulkanRenderer::BeginFrame(bool mainWindow) bool VulkanRenderer::BeginFrame(bool mainWindow)
{ {
if (!IsSwapchainInfoValid(mainWindow)) if (!AcquireNextSwapchainImage(mainWindow))
return false; return false;
AcquireNextSwapchainImage(mainWindow);
auto& chainInfo = GetChainInfo(mainWindow); auto& chainInfo = GetChainInfo(mainWindow);
VkClearColorValue clearColor{ 0, 0, 0, 0 }; VkClearColorValue clearColor{ 0, 0, 0, 0 };
@ -1743,9 +1744,6 @@ void VulkanRenderer::DrawEmptyFrame(bool mainWindow)
void VulkanRenderer::PreparePresentationFrame(bool mainWindow) void VulkanRenderer::PreparePresentationFrame(bool mainWindow)
{ {
if (!IsSwapchainInfoValid(mainWindow))
return;
AcquireNextSwapchainImage(mainWindow); AcquireNextSwapchainImage(mainWindow);
} }
@ -2530,11 +2528,36 @@ VkPipeline VulkanRenderer::backbufferBlit_createGraphicsPipeline(VkDescriptorSet
return pipeline; return pipeline;
} }
void VulkanRenderer::AcquireNextSwapchainImage(bool mainWindow) bool VulkanRenderer::AcquireNextSwapchainImage(bool mainWindow)
{ {
if(!IsSwapchainInfoValid(mainWindow))
return false;
if(!mainWindow && m_destroyPadSwapchainNextAcquire)
{
RecreateSwapchain(mainWindow, true);
m_destroyPadSwapchainNextAcquire = false;
m_padCloseReadySemaphore.notify();
return false;
}
auto& chainInfo = GetChainInfo(mainWindow); auto& chainInfo = GetChainInfo(mainWindow);
UpdateVSyncState(mainWindow);
const bool latteBufferUsesSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB;
if (chainInfo.sizeOutOfDate || chainInfo.m_usesSRGB != latteBufferUsesSRGB)
{
try
{
RecreateSwapchain(mainWindow);
chainInfo.m_usesSRGB = latteBufferUsesSRGB;
}
catch (std::exception&) { cemu_assert_debug(false); }
}
if (chainInfo.swapchainImageIndex != -1) if (chainInfo.swapchainImageIndex != -1)
return; // image already reserved return true; // image already reserved
vkWaitForFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence, VK_TRUE, std::numeric_limits<uint64_t>::max()); vkWaitForFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence, VK_TRUE, std::numeric_limits<uint64_t>::max());
vkResetFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence); vkResetFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence);
@ -2553,7 +2576,7 @@ void VulkanRenderer::AcquireNextSwapchainImage(bool mainWindow)
vkResetFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence); vkResetFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence);
result = vkAcquireNextImageKHR(m_logicalDevice, chainInfo.swapchain, std::numeric_limits<uint64_t>::max(), acquireSemaphore, chainInfo.m_imageAvailableFence, &chainInfo.swapchainImageIndex); result = vkAcquireNextImageKHR(m_logicalDevice, chainInfo.swapchain, std::numeric_limits<uint64_t>::max(), acquireSemaphore, chainInfo.m_imageAvailableFence, &chainInfo.swapchainImageIndex);
if (result == VK_SUCCESS) if (result == VK_SUCCESS)
return; return true;
} }
catch (std::exception&) {} catch (std::exception&) {}
@ -2565,11 +2588,11 @@ void VulkanRenderer::AcquireNextSwapchainImage(bool mainWindow)
} }
chainInfo.m_acquireIndex = (chainInfo.m_acquireIndex + 1) % chainInfo.m_acquireSemaphores.size(); chainInfo.m_acquireIndex = (chainInfo.m_acquireIndex + 1) % chainInfo.m_acquireSemaphores.size();
SubmitCommandBuffer(nullptr, &acquireSemaphore); SubmitCommandBuffer(nullptr, &acquireSemaphore);
return true;
} }
void VulkanRenderer::RecreateSwapchain(bool mainWindow) void VulkanRenderer::RecreateSwapchain(bool mainWindow, bool skipCreate)
{ {
SubmitCommandBuffer(); SubmitCommandBuffer();
WaitDeviceIdle(); WaitDeviceIdle();
@ -2591,7 +2614,10 @@ void VulkanRenderer::RecreateSwapchain(bool mainWindow)
chainInfo.Cleanup(); chainInfo.Cleanup();
chainInfo.setSize(size); chainInfo.setSize(size);
if(!skipCreate)
{
chainInfo.Create(m_physicalDevice, m_logicalDevice); chainInfo.Create(m_physicalDevice, m_logicalDevice);
}
chainInfo.swapchainImageIndex = -1; chainInfo.swapchainImageIndex = -1;
if (mainWindow) if (mainWindow)
@ -2610,23 +2636,10 @@ void VulkanRenderer::UpdateVSyncState(bool mainWindow)
void VulkanRenderer::SwapBuffer(bool mainWindow) void VulkanRenderer::SwapBuffer(bool mainWindow)
{ {
auto& chainInfo = GetChainInfo(mainWindow); if(!AcquireNextSwapchainImage(mainWindow))
const bool latteBufferUsesSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB;
if (chainInfo.sizeOutOfDate || chainInfo.m_usesSRGB != latteBufferUsesSRGB)
{
try
{
RecreateSwapchain(mainWindow);
chainInfo.m_usesSRGB = latteBufferUsesSRGB;
}
catch (std::exception&) { cemu_assert_debug(false); }
return; return;
}
UpdateVSyncState(mainWindow); auto& chainInfo = GetChainInfo(mainWindow);
AcquireNextSwapchainImage(mainWindow);
if (!chainInfo.hasDefinedSwapchainImage) if (!chainInfo.hasDefinedSwapchainImage)
{ {
@ -2818,7 +2831,7 @@ void VulkanRenderer::CreateBackbufferIndexBuffer()
void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutputShader* shader, bool useLinearTexFilter, sint32 imageX, sint32 imageY, sint32 imageWidth, sint32 imageHeight, bool padView, bool clearBackground) void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutputShader* shader, bool useLinearTexFilter, sint32 imageX, sint32 imageY, sint32 imageWidth, sint32 imageHeight, bool padView, bool clearBackground)
{ {
if (!IsSwapchainInfoValid(!padView)) if(!AcquireNextSwapchainImage(!padView))
return; return;
auto& chainInfo = GetChainInfo(!padView); auto& chainInfo = GetChainInfo(!padView);
@ -2828,8 +2841,6 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
if (clearBackground) if (clearBackground)
ClearColorbuffer(padView); ClearColorbuffer(padView);
AcquireNextSwapchainImage(!padView);
// barrier for input texture // barrier for input texture
VkMemoryBarrier memoryBarrier{}; VkMemoryBarrier memoryBarrier{};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;

View File

@ -187,6 +187,7 @@ public:
const std::unique_ptr<SwapchainInfoVk>& GetChainInfoPtr(bool mainWindow) const; const std::unique_ptr<SwapchainInfoVk>& GetChainInfoPtr(bool mainWindow) const;
SwapchainInfoVk& GetChainInfo(bool mainWindow) const; SwapchainInfoVk& GetChainInfo(bool mainWindow) const;
void StopUsingPadAndWait();
bool IsPadWindowActive() override; bool IsPadWindowActive() override;
void HandleScreenshotRequest(LatteTextureView* texView, bool padView) override; void HandleScreenshotRequest(LatteTextureView* texView, bool padView) override;
@ -432,6 +433,8 @@ private:
}m_state; }m_state;
std::unique_ptr<SwapchainInfoVk> m_mainSwapchainInfo{}, m_padSwapchainInfo{}; std::unique_ptr<SwapchainInfoVk> m_mainSwapchainInfo{}, m_padSwapchainInfo{};
Semaphore m_padCloseReadySemaphore;
bool m_destroyPadSwapchainNextAcquire = false;
bool IsSwapchainInfoValid(bool mainWindow) const; bool IsSwapchainInfoValid(bool mainWindow) const;
VkRenderPass m_imguiRenderPass = nullptr; VkRenderPass m_imguiRenderPass = nullptr;
@ -555,8 +558,8 @@ private:
void CreatePipelineCache(); void CreatePipelineCache();
VkPipelineShaderStageCreateInfo CreatePipelineShaderStageCreateInfo(VkShaderStageFlagBits stage, VkShaderModule& module, const char* entryName) const; VkPipelineShaderStageCreateInfo CreatePipelineShaderStageCreateInfo(VkShaderStageFlagBits stage, VkShaderModule& module, const char* entryName) const;
VkPipeline backbufferBlit_createGraphicsPipeline(VkDescriptorSetLayout descriptorLayout, bool padView, RendererOutputShader* shader); VkPipeline backbufferBlit_createGraphicsPipeline(VkDescriptorSetLayout descriptorLayout, bool padView, RendererOutputShader* shader);
void AcquireNextSwapchainImage(bool mainWindow); bool AcquireNextSwapchainImage(bool mainWindow);
void RecreateSwapchain(bool mainWindow); void RecreateSwapchain(bool mainWindow, bool skipCreate = false);
// streamout // streamout
void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) override; void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) override;

View File

@ -41,6 +41,12 @@ VulkanCanvas::~VulkanCanvas()
{ {
Unbind(wxEVT_PAINT, &VulkanCanvas::OnPaint, this); Unbind(wxEVT_PAINT, &VulkanCanvas::OnPaint, this);
Unbind(wxEVT_SIZE, &VulkanCanvas::OnResize, this); Unbind(wxEVT_SIZE, &VulkanCanvas::OnResize, this);
if(!m_is_main_window)
{
if(auto vulkan_renderer = VulkanRenderer::GetInstance())
vulkan_renderer->StopUsingPadAndWait();
}
} }
void VulkanCanvas::OnPaint(wxPaintEvent& event) void VulkanCanvas::OnPaint(wxPaintEvent& event)