1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[dxgi] Implement WaitForVBlank using new sleep helper

Not very accurate, but probably good enough if the display
refresh rate is known.
This commit is contained in:
Philip Rebohle 2022-09-15 14:57:03 +02:00
parent 3543673c5c
commit c56a9b5a3f
2 changed files with 39 additions and 4 deletions

View File

@ -2,6 +2,8 @@
#include "../dxvk/dxvk_include.h" #include "../dxvk/dxvk_include.h"
#include "../util/util_time.h"
#include "dxgi_format.h" #include "dxgi_format.h"
#include "dxgi_include.h" #include "dxgi_include.h"
@ -24,6 +26,7 @@ struct DXGI_VK_MONITOR_DATA {
dxvk::DxgiSwapChain* pSwapChain; dxvk::DxgiSwapChain* pSwapChain;
DXGI_FRAME_STATISTICS FrameStats; DXGI_FRAME_STATISTICS FrameStats;
DXGI_GAMMA_CONTROL GammaCurve; DXGI_GAMMA_CONTROL GammaCurve;
DXGI_MODE_DESC1 LastMode;
}; };

View File

@ -14,6 +14,10 @@
#include "../dxvk/dxvk_format.h" #include "../dxvk/dxvk_format.h"
#include "../util/util_misc.h"
#include "../util/util_sleep.h"
#include "../util/util_time.h"
namespace dxvk { namespace dxvk {
DxgiOutput::DxgiOutput( DxgiOutput::DxgiOutput(
@ -23,12 +27,16 @@ namespace dxvk {
: m_monitorInfo(factory->GetMonitorInfo()), : m_monitorInfo(factory->GetMonitorInfo()),
m_adapter(adapter), m_adapter(adapter),
m_monitor(monitor) { m_monitor(monitor) {
// Query current display mode
wsi::WsiMode activeWsiMode = { };
wsi::getCurrentDisplayMode(m_monitor, &activeWsiMode);
// Init monitor info if necessary // Init monitor info if necessary
DXGI_VK_MONITOR_DATA monitorData; DXGI_VK_MONITOR_DATA monitorData = { };
monitorData.pSwapChain = nullptr; monitorData.FrameStats.SyncQPCTime.QuadPart = dxvk::high_resolution_clock::get_counter();
monitorData.FrameStats = DXGI_FRAME_STATISTICS();
monitorData.GammaCurve.Scale = { 1.0f, 1.0f, 1.0f }; monitorData.GammaCurve.Scale = { 1.0f, 1.0f, 1.0f };
monitorData.GammaCurve.Offset = { 0.0f, 0.0f, 0.0f }; monitorData.GammaCurve.Offset = { 0.0f, 0.0f, 0.0f };
monitorData.LastMode = ConvertDisplayMode(activeWsiMode);
for (uint32_t i = 0; i < DXGI_VK_GAMMA_CP_COUNT; i++) { for (uint32_t i = 0; i < DXGI_VK_GAMMA_CP_COUNT; i++) {
const float value = GammaControlPointLocation(i); const float value = GammaControlPointLocation(i);
@ -443,7 +451,31 @@ namespace dxvk {
static bool s_errorShown = false; static bool s_errorShown = false;
if (!std::exchange(s_errorShown, true)) if (!std::exchange(s_errorShown, true))
Logger::warn("DxgiOutput::WaitForVBlank: Stub"); Logger::warn("DxgiOutput::WaitForVBlank: Inaccurate");
// Get monitor data to compute the sleep duration
DXGI_VK_MONITOR_DATA* monitorInfo = nullptr;
HRESULT hr = m_monitorInfo->AcquireMonitorData(m_monitor, &monitorInfo);
if (FAILED(hr))
return hr;
// Estimate number of vblanks since last mode
// change, then wait for one more refresh period
auto refreshPeriod = computeRefreshPeriod(
monitorInfo->LastMode.RefreshRate.Numerator,
monitorInfo->LastMode.RefreshRate.Denominator);
auto t0 = dxvk::high_resolution_clock::get_time_from_counter(monitorInfo->FrameStats.SyncQPCTime.QuadPart);
auto t1 = dxvk::high_resolution_clock::now();
uint64_t vblankCount = computeRefreshCount(t0, t1, refreshPeriod);
auto t2 = t0 + (vblankCount + 1) * refreshPeriod;
m_monitorInfo->ReleaseMonitorData();
// Sleep until the given time point
Sleep::sleepUntil(t1, t2);
return S_OK; return S_OK;
} }