Separate wait functions for swap chains.

This commit is contained in:
Skyth 2024-12-24 16:22:13 +03:00
parent d0a7205c9b
commit bc21f594c8
6 changed files with 40 additions and 15 deletions

View file

@ -1264,16 +1264,18 @@ namespace plume {
} }
bool D3D12SwapChain::present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) { bool D3D12SwapChain::present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) {
if (waitableObject != NULL) {
WaitForSingleObject(waitableObject, INFINITE);
}
UINT syncInterval = vsyncEnabled ? 1 : 0; UINT syncInterval = vsyncEnabled ? 1 : 0;
UINT flags = !vsyncEnabled ? DXGI_PRESENT_ALLOW_TEARING : 0; UINT flags = !vsyncEnabled ? DXGI_PRESENT_ALLOW_TEARING : 0;
HRESULT res = d3d->Present(syncInterval, flags); HRESULT res = d3d->Present(syncInterval, flags);
return SUCCEEDED(res); return SUCCEEDED(res);
} }
void D3D12SwapChain::wait() {
if (waitableObject != NULL) {
WaitForSingleObject(waitableObject, INFINITE);
}
}
bool D3D12SwapChain::resize() { bool D3D12SwapChain::resize() {
getWindowSize(width, height); getWindowSize(width, height);

View file

@ -111,6 +111,7 @@ namespace plume {
D3D12SwapChain(D3D12CommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format); D3D12SwapChain(D3D12CommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format);
~D3D12SwapChain() override; ~D3D12SwapChain() override;
bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) override; bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) override;
void wait() override;
bool resize() override; bool resize() override;
bool needsResize() const override; bool needsResize() const override;
void setVsyncEnabled(bool vsyncEnabled) override; void setVsyncEnabled(bool vsyncEnabled) override;

View file

@ -87,6 +87,7 @@ namespace plume {
struct RenderSwapChain { struct RenderSwapChain {
virtual ~RenderSwapChain() { } virtual ~RenderSwapChain() { }
virtual bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) = 0; virtual bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) = 0;
virtual void wait() = 0;
virtual bool resize() = 0; virtual bool resize() = 0;
virtual bool needsResize() const = 0; virtual bool needsResize() const = 0;
virtual void setVsyncEnabled(bool vsyncEnabled) = 0; virtual void setVsyncEnabled(bool vsyncEnabled) = 0;

View file

@ -2131,12 +2131,6 @@ namespace plume {
} }
bool VulkanSwapChain::present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) { 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<VkSemaphore> waitSemaphoresVector; thread_local std::vector<VkSemaphore> waitSemaphoresVector;
waitSemaphoresVector.clear(); waitSemaphoresVector.clear();
for (uint32_t i = 0; i < waitSemaphoreCount; i++) { for (uint32_t i = 0; i < waitSemaphoreCount; i++) {
@ -2175,6 +2169,14 @@ namespace plume {
return true; 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() { bool VulkanSwapChain::resize() {
getWindowSize(width, height); getWindowSize(width, height);

View file

@ -235,6 +235,7 @@ namespace plume {
VulkanSwapChain(VulkanCommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format); VulkanSwapChain(VulkanCommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format);
~VulkanSwapChain() override; ~VulkanSwapChain() override;
bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) override; bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) override;
void wait() override;
bool resize() override; bool resize() override;
bool needsResize() const override; bool needsResize() const override;
void setVsyncEnabled(bool vsyncEnabled) override; void setVsyncEnabled(bool vsyncEnabled) override;

View file

@ -1574,11 +1574,26 @@ void Video::WaitForGPU()
} }
} }
static std::atomic<bool> g_pendingRenderThread; enum class RenderThreadState
{
ProcessingPresent,
PendingWaitOnSwapChain,
PendingPresent
};
static std::atomic<RenderThreadState> g_renderThreadState = RenderThreadState::PendingWaitOnSwapChain;
static void WaitForRenderThread() 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() static void BeginCommandList()
@ -2187,7 +2202,8 @@ void Video::HostPresent()
WaitForRenderThread(); WaitForRenderThread();
DrawImGui(); DrawImGui();
g_pendingRenderThread.store(true); assert(g_renderThreadState == RenderThreadState::PendingPresent);
g_renderThreadState = RenderThreadState::ProcessingPresent;
RenderCommand cmd; RenderCommand cmd;
cmd.type = RenderCommandType::Present; cmd.type = RenderCommandType::Present;
@ -2228,6 +2244,8 @@ static void SetRootDescriptor(const UploadAllocation& allocation, size_t index)
static void ProcPresent(const RenderCommand& cmd) static void ProcPresent(const RenderCommand& cmd)
{ {
assert(g_renderThreadState == RenderThreadState::ProcessingPresent);
if (g_swapChainValid) if (g_swapChainValid)
{ {
auto swapChainTexture = g_swapChain->getTexture(g_backBufferIndex); auto swapChainTexture = g_swapChain->getTexture(g_backBufferIndex);
@ -2361,8 +2379,8 @@ static void ProcPresent(const RenderCommand& cmd)
BeginCommandList(); BeginCommandList();
g_pendingRenderThread.store(false); g_renderThreadState = RenderThreadState::PendingWaitOnSwapChain;
g_pendingRenderThread.notify_all(); g_renderThreadState.notify_all();
} }
static GuestSurface* GetBackBuffer() static GuestSurface* GetBackBuffer()