diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index f3a3ab46..3a219b7b 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -676,6 +676,12 @@ SwapchainInfoVk& VulkanRenderer::GetChainInfo(bool mainWindow) const return *GetChainInfoPtr(mainWindow); } +void VulkanRenderer::StopUsingPadAndWait() +{ + m_destroyPadSwapchainNextAcquire = true; + m_padCloseReadySemaphore.wait(); +} + bool VulkanRenderer::IsPadWindowActive() { return IsSwapchainInfoValid(false); @@ -1658,15 +1664,12 @@ bool VulkanRenderer::ImguiBegin(bool mainWindow) auto& chainInfo = GetChainInfo(mainWindow); - if (!IsSwapchainInfoValid(mainWindow)) + if (!AcquireNextSwapchainImage(mainWindow)) return false; draw_endRenderPass(); m_state.currentPipeline = VK_NULL_HANDLE; - AcquireNextSwapchainImage(mainWindow); - - ImGui_ImplVulkan_CreateFontsTexture(m_state.currentCommandBuffer); ImGui_ImplVulkan_NewFrame(m_state.currentCommandBuffer, chainInfo.m_swapchainFramebuffers[chainInfo.swapchainImageIndex], chainInfo.swapchainExtent); ImGui_UpdateWindowInformation(mainWindow); @@ -1718,11 +1721,9 @@ void VulkanRenderer::DeleteFontTextures() bool VulkanRenderer::BeginFrame(bool mainWindow) { - if (!IsSwapchainInfoValid(mainWindow)) + if (!AcquireNextSwapchainImage(mainWindow)) return false; - AcquireNextSwapchainImage(mainWindow); - auto& chainInfo = GetChainInfo(mainWindow); VkClearColorValue clearColor{ 0, 0, 0, 0 }; @@ -1743,9 +1744,6 @@ void VulkanRenderer::DrawEmptyFrame(bool mainWindow) void VulkanRenderer::PreparePresentationFrame(bool mainWindow) { - if (!IsSwapchainInfoValid(mainWindow)) - return; - AcquireNextSwapchainImage(mainWindow); } @@ -2530,11 +2528,36 @@ VkPipeline VulkanRenderer::backbufferBlit_createGraphicsPipeline(VkDescriptorSet 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); + + 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) - return; // image already reserved + return true; // image already reserved vkWaitForFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence, VK_TRUE, std::numeric_limits::max()); vkResetFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence); @@ -2553,7 +2576,7 @@ void VulkanRenderer::AcquireNextSwapchainImage(bool mainWindow) vkResetFences(m_logicalDevice, 1, &chainInfo.m_imageAvailableFence); result = vkAcquireNextImageKHR(m_logicalDevice, chainInfo.swapchain, std::numeric_limits::max(), acquireSemaphore, chainInfo.m_imageAvailableFence, &chainInfo.swapchainImageIndex); if (result == VK_SUCCESS) - return; + return true; } catch (std::exception&) {} @@ -2565,11 +2588,11 @@ void VulkanRenderer::AcquireNextSwapchainImage(bool mainWindow) } chainInfo.m_acquireIndex = (chainInfo.m_acquireIndex + 1) % chainInfo.m_acquireSemaphores.size(); - SubmitCommandBuffer(nullptr, &acquireSemaphore); + return true; } -void VulkanRenderer::RecreateSwapchain(bool mainWindow) +void VulkanRenderer::RecreateSwapchain(bool mainWindow, bool skipCreate) { SubmitCommandBuffer(); WaitDeviceIdle(); @@ -2591,7 +2614,10 @@ void VulkanRenderer::RecreateSwapchain(bool mainWindow) chainInfo.Cleanup(); chainInfo.setSize(size); - chainInfo.Create(m_physicalDevice, m_logicalDevice); + if(!skipCreate) + { + chainInfo.Create(m_physicalDevice, m_logicalDevice); + } chainInfo.swapchainImageIndex = -1; if (mainWindow) @@ -2610,23 +2636,10 @@ void VulkanRenderer::UpdateVSyncState(bool mainWindow) void VulkanRenderer::SwapBuffer(bool mainWindow) { - auto& chainInfo = GetChainInfo(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(!AcquireNextSwapchainImage(mainWindow)) return; - } - UpdateVSyncState(mainWindow); - - AcquireNextSwapchainImage(mainWindow); + auto& chainInfo = GetChainInfo(mainWindow); 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) { - if (!IsSwapchainInfoValid(!padView)) + if(!AcquireNextSwapchainImage(!padView)) return; auto& chainInfo = GetChainInfo(!padView); @@ -2828,8 +2841,6 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu if (clearBackground) ClearColorbuffer(padView); - AcquireNextSwapchainImage(!padView); - // barrier for input texture VkMemoryBarrier memoryBarrier{}; memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h index 6ff2f237..941aaca8 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h @@ -187,6 +187,7 @@ public: const std::unique_ptr& GetChainInfoPtr(bool mainWindow) const; SwapchainInfoVk& GetChainInfo(bool mainWindow) const; + void StopUsingPadAndWait(); bool IsPadWindowActive() override; void HandleScreenshotRequest(LatteTextureView* texView, bool padView) override; @@ -432,6 +433,8 @@ private: }m_state; std::unique_ptr m_mainSwapchainInfo{}, m_padSwapchainInfo{}; + Semaphore m_padCloseReadySemaphore; + bool m_destroyPadSwapchainNextAcquire = false; bool IsSwapchainInfoValid(bool mainWindow) const; VkRenderPass m_imguiRenderPass = nullptr; @@ -555,8 +558,8 @@ private: void CreatePipelineCache(); VkPipelineShaderStageCreateInfo CreatePipelineShaderStageCreateInfo(VkShaderStageFlagBits stage, VkShaderModule& module, const char* entryName) const; VkPipeline backbufferBlit_createGraphicsPipeline(VkDescriptorSetLayout descriptorLayout, bool padView, RendererOutputShader* shader); - void AcquireNextSwapchainImage(bool mainWindow); - void RecreateSwapchain(bool mainWindow); + bool AcquireNextSwapchainImage(bool mainWindow); + void RecreateSwapchain(bool mainWindow, bool skipCreate = false); // streamout void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) override; diff --git a/src/gui/canvas/VulkanCanvas.cpp b/src/gui/canvas/VulkanCanvas.cpp index 46428216..c16f3288 100644 --- a/src/gui/canvas/VulkanCanvas.cpp +++ b/src/gui/canvas/VulkanCanvas.cpp @@ -41,6 +41,12 @@ VulkanCanvas::~VulkanCanvas() { Unbind(wxEVT_PAINT, &VulkanCanvas::OnPaint, 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)