GPU: Further improve vsync handling

This commit is contained in:
Stenzek
2024-05-24 01:59:35 +10:00
parent 4e922a34a7
commit 42a5fe0a6e
20 changed files with 184 additions and 163 deletions

View File

@ -201,7 +201,7 @@ u32 D3D11Device::GetSwapChainBufferCount() const
{
// With vsync off, we only need two buffers. Same for blocking vsync.
// With triple buffering, we need three.
return (m_vsync_enabled && m_vsync_prefer_triple_buffer) ? 3 : 2;
return (m_vsync_mode == GPUVSyncMode::TripleBuffered) ? 3 : 2;
}
bool D3D11Device::CreateSwapChain()
@ -357,10 +357,6 @@ bool D3D11Device::CreateSwapChainRTV()
m_window_info.surface_refresh_rate = static_cast<float>(desc.BufferDesc.RefreshRate.Numerator) /
static_cast<float>(desc.BufferDesc.RefreshRate.Denominator);
}
else
{
m_window_info.surface_refresh_rate = 0.0f;
}
}
return true;
@ -592,31 +588,13 @@ void D3D11Device::InvalidateRenderTarget(GPUTexture* t)
static_cast<D3D11Texture*>(t)->CommitClear(m_context.Get());
}
std::optional<float> D3D11Device::GetHostRefreshRate()
void D3D11Device::SetVSyncMode(GPUVSyncMode mode)
{
if (m_swap_chain && m_is_exclusive_fullscreen)
{
DXGI_SWAP_CHAIN_DESC desc;
if (SUCCEEDED(m_swap_chain->GetDesc(&desc)) && desc.BufferDesc.RefreshRate.Numerator > 0 &&
desc.BufferDesc.RefreshRate.Denominator > 0)
{
DEV_LOG("using fs rr: {} {}", desc.BufferDesc.RefreshRate.Numerator, desc.BufferDesc.RefreshRate.Denominator);
return static_cast<float>(desc.BufferDesc.RefreshRate.Numerator) /
static_cast<float>(desc.BufferDesc.RefreshRate.Denominator);
}
}
return GPUDevice::GetHostRefreshRate();
}
void D3D11Device::SetVSyncEnabled(bool enabled, bool prefer_triple_buffer)
{
if (m_vsync_enabled == enabled && m_vsync_prefer_triple_buffer == prefer_triple_buffer)
if (m_vsync_mode == mode)
return;
const u32 old_buffer_count = GetSwapChainBufferCount();
m_vsync_enabled = enabled;
m_vsync_prefer_triple_buffer = prefer_triple_buffer;
m_vsync_mode = mode;
if (!m_swap_chain)
return;
@ -656,7 +634,7 @@ bool D3D11Device::BeginPresent(bool skip_present)
// This blows our our GPU usage number considerably, so read the timestamp before the final blit
// in this configuration. It does reduce accuracy a little, but better than seeing 100% all of
// the time, when it's more like a couple of percent.
if (m_vsync_enabled && m_gpu_timing_enabled)
if (IsVSyncModeBlocking() && m_gpu_timing_enabled)
PopTimestampQuery();
static constexpr float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
@ -674,12 +652,12 @@ void D3D11Device::EndPresent(bool explicit_present)
DebugAssert(!explicit_present);
DebugAssert(m_num_current_render_targets == 0 && !m_current_depth_target);
if (!m_vsync_enabled && m_gpu_timing_enabled)
if (!IsVSyncModeBlocking() && m_gpu_timing_enabled)
PopTimestampQuery();
// DirectX has no concept of tear-or-sync. I guess if we measured times ourselves, we could implement it.
if (m_vsync_enabled)
m_swap_chain->Present(BoolToUInt32(1), 0);
if (IsVSyncModeBlocking())
m_swap_chain->Present(1, 0);
else if (m_using_allow_tearing) // Disabled or VRR, VRR requires the allow tearing flag :/
m_swap_chain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
else