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) {
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);

View file

@ -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;

View file

@ -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;

View file

@ -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<VkSemaphore> 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);

View file

@ -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;

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()
{
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()