diff --git a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp index 6c28cdf6..8b2e5e4f 100644 --- a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp +++ b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp @@ -1264,16 +1264,18 @@ namespace plume { } bool D3D12SwapChain::present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) { - if (waitableObject != NULL) { - WaitForSingleObject(waitableObject, INFINITE); - } - UINT syncInterval = vsyncEnabled ? 1 : 0; UINT flags = !vsyncEnabled ? DXGI_PRESENT_ALLOW_TEARING : 0; HRESULT res = d3d->Present(syncInterval, flags); return SUCCEEDED(res); } + void D3D12SwapChain::wait() { + if (waitableObject != NULL) { + WaitForSingleObject(waitableObject, INFINITE); + } + } + bool D3D12SwapChain::resize() { getWindowSize(width, height); diff --git a/UnleashedRecomp/gpu/rhi/plume_d3d12.h b/UnleashedRecomp/gpu/rhi/plume_d3d12.h index 464a1398..c1a160c5 100644 --- a/UnleashedRecomp/gpu/rhi/plume_d3d12.h +++ b/UnleashedRecomp/gpu/rhi/plume_d3d12.h @@ -111,6 +111,7 @@ namespace plume { D3D12SwapChain(D3D12CommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format); ~D3D12SwapChain() override; bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) override; + void wait() override; bool resize() override; bool needsResize() const override; void setVsyncEnabled(bool vsyncEnabled) override; diff --git a/UnleashedRecomp/gpu/rhi/plume_render_interface.h b/UnleashedRecomp/gpu/rhi/plume_render_interface.h index 1360e177..bc09e6fb 100644 --- a/UnleashedRecomp/gpu/rhi/plume_render_interface.h +++ b/UnleashedRecomp/gpu/rhi/plume_render_interface.h @@ -87,6 +87,7 @@ namespace plume { struct RenderSwapChain { virtual ~RenderSwapChain() { } virtual bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) = 0; + virtual void wait() = 0; virtual bool resize() = 0; virtual bool needsResize() const = 0; virtual void setVsyncEnabled(bool vsyncEnabled) = 0; diff --git a/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp b/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp index 89334cef..7e10ae9a 100644 --- a/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp +++ b/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp @@ -2131,12 +2131,6 @@ namespace plume { } bool VulkanSwapChain::present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) { - constexpr uint64_t MaxFrameDelay = 1; - if (commandQueue->device->capabilities.presentWait && (currentPresentId > MaxFrameDelay)) { - constexpr uint64_t waitTimeout = 100000000; - vkWaitForPresentKHR(commandQueue->device->vk, vk, currentPresentId - MaxFrameDelay, waitTimeout); - } - thread_local std::vector waitSemaphoresVector; waitSemaphoresVector.clear(); for (uint32_t i = 0; i < waitSemaphoreCount; i++) { @@ -2175,6 +2169,14 @@ namespace plume { return true; } + void VulkanSwapChain::wait() { + constexpr uint64_t MaxFrameDelay = 1; + if (commandQueue->device->capabilities.presentWait && (currentPresentId > MaxFrameDelay)) { + constexpr uint64_t waitTimeout = 100000000; + vkWaitForPresentKHR(commandQueue->device->vk, vk, currentPresentId - MaxFrameDelay, waitTimeout); + } + } + bool VulkanSwapChain::resize() { getWindowSize(width, height); diff --git a/UnleashedRecomp/gpu/rhi/plume_vulkan.h b/UnleashedRecomp/gpu/rhi/plume_vulkan.h index 6ffe5aa3..1e1d18d3 100644 --- a/UnleashedRecomp/gpu/rhi/plume_vulkan.h +++ b/UnleashedRecomp/gpu/rhi/plume_vulkan.h @@ -235,6 +235,7 @@ namespace plume { VulkanSwapChain(VulkanCommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format); ~VulkanSwapChain() override; bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) override; + void wait() override; bool resize() override; bool needsResize() const override; void setVsyncEnabled(bool vsyncEnabled) override; diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index dd2c9f5d..9fea39ff 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -1574,11 +1574,26 @@ void Video::WaitForGPU() } } -static std::atomic g_pendingRenderThread; +enum class RenderThreadState +{ + ProcessingPresent, + PendingWaitOnSwapChain, + PendingPresent +}; + +static std::atomic g_renderThreadState = RenderThreadState::PendingWaitOnSwapChain; static void WaitForRenderThread() { - g_pendingRenderThread.wait(true); + g_renderThreadState.wait(RenderThreadState::ProcessingPresent); + + if (g_renderThreadState == RenderThreadState::PendingWaitOnSwapChain) + { + if (g_swapChainValid) + g_swapChain->wait(); + + g_renderThreadState = RenderThreadState::PendingPresent; + } } static void BeginCommandList() @@ -2187,7 +2202,8 @@ void Video::HostPresent() WaitForRenderThread(); DrawImGui(); - g_pendingRenderThread.store(true); + assert(g_renderThreadState == RenderThreadState::PendingPresent); + g_renderThreadState = RenderThreadState::ProcessingPresent; RenderCommand cmd; cmd.type = RenderCommandType::Present; @@ -2228,6 +2244,8 @@ static void SetRootDescriptor(const UploadAllocation& allocation, size_t index) static void ProcPresent(const RenderCommand& cmd) { + assert(g_renderThreadState == RenderThreadState::ProcessingPresent); + if (g_swapChainValid) { auto swapChainTexture = g_swapChain->getTexture(g_backBufferIndex); @@ -2361,8 +2379,8 @@ static void ProcPresent(const RenderCommand& cmd) BeginCommandList(); - g_pendingRenderThread.store(false); - g_pendingRenderThread.notify_all(); + g_renderThreadState = RenderThreadState::PendingWaitOnSwapChain; + g_renderThreadState.notify_all(); } static GuestSurface* GetBackBuffer()