1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-30 02:52:10 +01:00

[d3d11] Re-implement frame latency events using Win32 semaphore

Matches native DXGI behaviour more accurately, and fixes a hang in
Shin Megami Tensei 3.
This commit is contained in:
Philip Rebohle 2021-08-02 19:11:35 +02:00
parent 4c222ec557
commit 56395c9bc8
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 16 additions and 8 deletions

View File

@ -177,9 +177,16 @@ namespace dxvk {
if (MaxLatency == 0 || MaxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS)
return DXGI_ERROR_INVALID_CALL;
m_frameLatency = MaxLatency;
if (m_frameLatencyEvent) {
// Windows DXGI does not seem to handle the case where the new maximum
// latency is less than the current value, and some games relying on
// this behaviour will hang if we attempt to decrement the semaphore.
// Thus, only increment the semaphore as necessary.
if (MaxLatency > m_frameLatency)
ReleaseSemaphore(m_frameLatencyEvent, MaxLatency - m_frameLatency, nullptr);
}
SyncFrameLatency();
m_frameLatency = MaxLatency;
return S_OK;
}
@ -367,10 +374,10 @@ namespace dxvk {
void D3D11SwapChain::CreateFrameLatencyEvent() {
m_frameLatencySignal = new sync::Win32Fence(m_frameId);
m_frameLatencySignal = new sync::CallbackFence(m_frameId);
if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)
m_frameLatencyEvent = CreateEvent(nullptr, false, true, nullptr);
m_frameLatencyEvent = CreateSemaphore(nullptr, m_frameLatency, DXGI_MAX_SWAP_CHAIN_BUFFERS, nullptr);
}
@ -558,8 +565,9 @@ namespace dxvk {
m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency());
if (m_frameLatencyEvent) {
// Signal event with the same value that we'd wait for during the next present.
m_frameLatencySignal->setEvent(m_frameLatencyEvent, m_frameId - GetActualFrameLatency() + 1);
m_frameLatencySignal->setCallback(m_frameId, [cFrameLatencyEvent = m_frameLatencyEvent] () {
ReleaseSemaphore(cFrameLatencyEvent, 1, nullptr);
});
}
}

View File

@ -6,7 +6,7 @@
#include "../dxvk/dxvk_swapchain_blitter.h"
#include "../util/sync/sync_signal_win32.h"
#include "../util/sync/sync_signal.h"
namespace dxvk {
@ -107,7 +107,7 @@ namespace dxvk {
uint32_t m_frameLatency = DefaultFrameLatency;
uint32_t m_frameLatencyCap = 0;
HANDLE m_frameLatencyEvent = nullptr;
Rc<sync::Win32Fence> m_frameLatencySignal;
Rc<sync::CallbackFence> m_frameLatencySignal;
bool m_dirty = true;
bool m_vsync = true;