From 16b062d17d3b162c4bb50bcec8c87ec7e4eadedd Mon Sep 17 00:00:00 2001 From: narzoul Date: Fri, 23 Aug 2024 23:17:35 +0200 Subject: [PATCH] Added VSync=wait setting --- DDrawCompat/Config/Settings/VSync.cpp | 4 +- DDrawCompat/Config/Settings/VSync.h | 2 +- DDrawCompat/DDraw/RealPrimarySurface.cpp | 23 ++++---- .../DDraw/Surfaces/PrimarySurfaceImpl.cpp | 56 +++++++++++++++---- Tools/DDrawCompat.ini | 8 ++- 5 files changed, 65 insertions(+), 28 deletions(-) diff --git a/DDrawCompat/Config/Settings/VSync.cpp b/DDrawCompat/Config/Settings/VSync.cpp index 418adce..096b7da 100644 --- a/DDrawCompat/Config/Settings/VSync.cpp +++ b/DDrawCompat/Config/Settings/VSync.cpp @@ -8,13 +8,13 @@ namespace Config namespace Settings { VSync::VSync() - : EnumSetting("VSync", "app", { "app", "off", "on" }) + : EnumSetting("VSync", "app", { "app", "off", "on", "wait"}) { } Setting::ParamInfo VSync::getParamInfo() const { - if (ON == m_value) + if (ON == m_value || WAIT == m_value) { return { "Interval", 1, 16, 1 }; } diff --git a/DDrawCompat/Config/Settings/VSync.h b/DDrawCompat/Config/Settings/VSync.h index 10e235f..7176d25 100644 --- a/DDrawCompat/Config/Settings/VSync.h +++ b/DDrawCompat/Config/Settings/VSync.h @@ -9,7 +9,7 @@ namespace Config class VSync : public EnumSetting { public: - enum Values { APP, OFF, ON }; + enum Values { APP, OFF, ON, WAIT }; VSync(); diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index 47840d8..b8a4119 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -99,10 +99,13 @@ namespace UINT getFlipInterval(DWORD flags) { - auto vSync = Config::vSync.get(); - if (Config::Settings::VSync::APP != vSync) + switch (Config::vSync.get()) { - return Config::Settings::VSync::OFF == vSync ? 0 : Config::vSync.getParam(); + case Config::Settings::VSync::OFF: + case Config::Settings::VSync::WAIT: + return 0; + case Config::Settings::VSync::ON: + return Config::vSync.getParam(); } if (flags & DDFLIP_NOVSYNC) @@ -734,12 +737,17 @@ namespace DDraw return true; } + bool isUpdateReady = g_isUpdateReady; auto qpcStart = Time::queryPerformanceCounter(); auto vsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter(); while (static_cast(vsyncCount - g_flipEndVsyncCount) < 0) { ++vsyncCount; D3dDdi::KernelModeThunks::waitForVsyncCounter(vsyncCount); + if (isUpdateReady) + { + flush(); + } } Compat::ScopedCriticalSection lock(g_presentCs); @@ -764,10 +772,10 @@ namespace DDraw g_qpcPrevWaitEnd = qpcWaitEnd; Compat::ScopedThreadPriority prio(THREAD_PRIORITY_TIME_CRITICAL); - auto qpcStart = Time::queryPerformanceCounter(); while (Time::qpcToMs(qpcWaitEnd - qpcNow) > 0) { Time::waitForNextTick(); + flush(); qpcNow = Time::queryPerformanceCounter(); } @@ -775,12 +783,5 @@ namespace DDraw { qpcNow = Time::queryPerformanceCounter(); } - - Compat::ScopedCriticalSection lock(g_presentCs); - auto qpcEnd = Time::queryPerformanceCounter(); - if (g_isUpdatePending) - { - g_qpcUpdateStart += qpcEnd - qpcStart; - } } } diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp index 3c605fe..8e6f3c2 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -177,18 +178,22 @@ namespace DDraw caps.dwCaps = DDSCAPS_BACKBUFFER; getOrigVtable(This).GetAttachedSurface(This, &caps, &surfaceTargetOverride.getRef()); } - HRESULT result = Blt(This, nullptr, surfaceTargetOverride.get(), nullptr, DDBLT_WAIT, nullptr); - if (SUCCEEDED(result) && Config::Settings::FpsLimiter::FLIPEND == Config::fpsLimiter.get()) - { - RealPrimarySurface::waitForFlipFpsLimit(); - } - return result; - } - HRESULT result = SurfaceImpl::Flip(This, surfaceTargetOverride, DDFLIP_WAIT); - if (FAILED(result)) + HRESULT result = SurfaceImpl::Blt(This, nullptr, surfaceTargetOverride.get(), nullptr, DDBLT_WAIT, nullptr); + if (FAILED(result)) + { + return result; + } + + dwFlags = DDFLIP_NOVSYNC; + } + else { - return result; + HRESULT result = SurfaceImpl::Flip(This, surfaceTargetOverride, DDFLIP_WAIT); + if (FAILED(result)) + { + return result; + } } auto statsWindow = Gdi::GuiThread::getStatsWindow(); @@ -199,10 +204,37 @@ namespace DDraw PrimarySurface::updateFrontResource(); RealPrimarySurface::flip(surfaceTargetOverride, dwFlags); - PrimarySurface::waitForIdle(); + + if (Config::Settings::VSync::WAIT == Config::vSync.get()) + { + static UINT lastFlipEnd = 0; + lastFlipEnd += Config::vSync.getParam(); + UINT vsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter(); + if (static_cast(vsyncCount - lastFlipEnd) > 0) + { + lastFlipEnd = vsyncCount; + } + + RealPrimarySurface::setUpdateReady(); + if (0 != RealPrimarySurface::flush()) + { + PrimarySurface::waitForIdle(); + } + + while (static_cast(vsyncCount - lastFlipEnd) < 0) + { + ++vsyncCount; + D3dDdi::KernelModeThunks::waitForVsyncCounter(vsyncCount); + RealPrimarySurface::flush(); + } + } + else + { + PrimarySurface::waitForIdle(); + } + if (Config::Settings::FpsLimiter::FLIPEND == Config::fpsLimiter.get()) { - DDraw::RealPrimarySurface::waitForFlip(m_data->getDDS()); RealPrimarySurface::waitForFlipFpsLimit(); } return DD_OK; diff --git a/Tools/DDrawCompat.ini b/Tools/DDrawCompat.ini index f7cb9ec..84a71d1 100644 --- a/Tools/DDrawCompat.ini +++ b/Tools/DDrawCompat.ini @@ -22,10 +22,11 @@ # ForceD3D9On12 = off # FpsLimiter = off # FullscreenMode = borderless +# GdiStretchBltMode = app # LogLevel = info # PalettizedTextures = off # RemoveBorders = off -# RenderColorDepth = appd8 +# RenderColorDepth = 32 # ResolutionScale = app(1) # ResolutionScaleFilter = point # SoftwareDevice = rgb @@ -37,15 +38,18 @@ # StatsHotKey = shift+f12 # StatsPosX = right # StatsPosY = top -# StatsRows = label, presentrate, fliprate, blitcount, lockcount, ddiusage +# StatsRows = label, presentrate, fliprate, blitcount, lockcount # StatsTransparency = alpha(75) # StatsUpdateRate = 5 # SupportedDepthFormats = all # SupportedResolutions = native, 640x480, 800x600, 1024x768 # SupportedTextureFormats = all +# SurfacePatches = none # TerminateHotKey = ctrl+alt+end # TextureFilter = app # ThreadPriorityBoost = off # VSync = app # VertexBufferMemoryType = sysmem +# VertexFixup = gpu +# ViewportEdgeFix = off # WinVersionLie = off