From 3c1e8abcfe0e4404e21074e9db6a4770502f8b0c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 29 Feb 2020 22:27:00 -0800 Subject: [PATCH 1/4] GPU: Centralize vsync interval logic. We already do unthrottle checking here. --- GPU/D3D11/GPU_D3D11.cpp | 1 - GPU/D3D11/GPU_D3D11.h | 2 -- GPU/Directx9/GPU_DX9.cpp | 11 ----------- GPU/Directx9/GPU_DX9.h | 2 -- GPU/GLES/GPU_GLES.cpp | 32 +------------------------------- GPU/GLES/GPU_GLES.h | 6 ------ GPU/GPUCommon.cpp | 27 +++++++++++++++++++++++++++ GPU/GPUCommon.h | 5 +++++ GPU/Vulkan/GPU_Vulkan.cpp | 5 ----- GPU/Vulkan/GPU_Vulkan.h | 1 - ext/native/gfx/d3d9_state.cpp | 3 --- ext/native/gfx/d3d9_state.h | 3 --- 12 files changed, 33 insertions(+), 65 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 9f2c4474e9de..7b5aca935a2b 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -73,7 +73,6 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); D3D_FEATURE_LEVEL featureLevel = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL); - lastVsync_ = g_Config.bVSync ? 1 : 0; stockD3D11.Create(device_); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 781cc5f1fbfe..0d16020013cb 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -81,6 +81,4 @@ class GPU_D3D11 : public GPUCommon { DepalShaderCacheD3D11 *depalShaderCache_; DrawEngineD3D11 drawEngine_; ShaderManagerD3D11 *shaderManagerD3D11_; - - int lastVsync_; }; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index f54bd4e0717c..70d1d3f4e304 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -58,8 +58,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) drawEngine_(draw) { device_ = (LPDIRECT3DDEVICE9)draw->GetNativeObject(Draw::NativeObject::DEVICE); deviceEx_ = (LPDIRECT3DDEVICE9EX)draw->GetNativeObject(Draw::NativeObject::DEVICE_EX); - lastVsync_ = g_Config.bVSync ? 1 : 0; - dxstate.SetVSyncInterval(g_Config.bVSync); shaderManagerDX9_ = new ShaderManagerDX9(draw, device_); framebufferManagerDX9_ = new FramebufferManagerDX9(draw); @@ -285,15 +283,6 @@ void GPU_DX9::ReapplyGfxState() { } void GPU_DX9::BeginFrame() { - // Turn off vsync when unthrottled - int desiredVSyncInterval = g_Config.bVSync ? 1 : 0; - if (PSP_CoreParameter().unthrottle || PSP_CoreParameter().fpsLimit != FPSLimit::NORMAL) - desiredVSyncInterval = 0; - if (desiredVSyncInterval != lastVsync_) { - dxstate.SetVSyncInterval(desiredVSyncInterval); - lastVsync_ = desiredVSyncInterval; - } - textureCacheDX9_->StartFrame(); drawEngine_.DecimateTrackedVertexArrays(); depalShaderCache_.Decimate(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 5bf58fd1363c..ac5407362a78 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -80,8 +80,6 @@ class GPU_DX9 : public GPUCommon { DepalShaderCacheDX9 depalShaderCache_; DrawEngineDX9 drawEngine_; ShaderManagerDX9 *shaderManagerDX9_; - - int lastVsync_; }; } // namespace DX9 diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 97b0ecf17849..b29635d7b389 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -360,6 +360,7 @@ void GPU_GLES::BeginHostFrame() { drawEngine_.Resized(); shaderManagerGL_->DirtyShader(); textureCacheGL_->NotifyConfigChanged(); + resized_ = false; } drawEngine_.BeginFrame(); @@ -369,42 +370,11 @@ void GPU_GLES::EndHostFrame() { drawEngine_.EndFrame(); } -inline void GPU_GLES::UpdateVsyncInterval(bool force) { -#ifdef _WIN32 - int desiredVSyncInterval = g_Config.bVSync ? 1 : 0; - if (PSP_CoreParameter().unthrottle) { - desiredVSyncInterval = 0; - } - if (PSP_CoreParameter().fpsLimit != FPSLimit::NORMAL) { - int limit = PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 ? g_Config.iFpsLimit1 : g_Config.iFpsLimit2; - // For an alternative speed that is a clean factor of 60, the user probably still wants vsync. - if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) { - desiredVSyncInterval = 0; - } - } - - if (desiredVSyncInterval != lastVsync_ || force) { - // Disabled EXT_swap_control_tear for now, it never seems to settle at the correct timing - // so it just keeps tearing. Not what I hoped for... - //if (gl_extensions.EXT_swap_control_tear) { - // // See http://developer.download.nvidia.com/opengl/specs/WGL_EXT_swap_control_tear.txt - // glstate.SetVSyncInterval(-desiredVSyncInterval); - //} else { - gfxCtx_->SwapInterval(desiredVSyncInterval); - //} - lastVsync_ = desiredVSyncInterval; - } -#endif -} - void GPU_GLES::ReapplyGfxState() { GPUCommon::ReapplyGfxState(); } void GPU_GLES::BeginFrame() { - UpdateVsyncInterval(resized_); - resized_ = false; - textureCacheGL_->StartFrame(); drawEngine_.DecimateTrackedVertexArrays(); depalShaderCache_.Decimate(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 9aa78825c179..351a3ea16728 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -79,8 +79,6 @@ class GPU_GLES : public GPUCommon { void CopyDisplayToOutput() override; void Reinitialize() override; - inline void UpdateVsyncInterval(bool force); - FramebufferManagerGLES *framebufferManagerGL_; TextureCacheGLES *textureCacheGL_; DepalShaderCacheGLES depalShaderCache_; @@ -89,8 +87,4 @@ class GPU_GLES : public GPUCommon { ShaderManagerGLES *shaderManagerGL_; std::string shaderCachePath_; - -#ifdef _WIN32 - int lastVsync_; -#endif }; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 649a37f4d1b6..d82964d7fb6a 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -6,6 +6,7 @@ #include "profiler/profiler.h" #include "Common/ColorConv.h" +#include "Common/GraphicsContext.h" #include "Core/Reporting.h" #include "GPU/GeDisasm.h" #include "GPU/GPU.h" @@ -408,6 +409,7 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : } UpdateCmdInfo(); + UpdateVsyncInterval(true); } GPUCommon::~GPUCommon() { @@ -432,6 +434,7 @@ void GPUCommon::UpdateCmdInfo() { } void GPUCommon::BeginHostFrame() { + UpdateVsyncInterval(resized_); ReapplyGfxState(); // TODO: Assume config may have changed - maybe move to resize. @@ -458,6 +461,30 @@ void GPUCommon::Reinitialize() { interruptsEnabled_ = true; } +void GPUCommon::UpdateVsyncInterval(bool force) { +#ifdef _WIN32 + int desiredVSyncInterval = g_Config.bVSync ? 1 : 0; + if (PSP_CoreParameter().unthrottle) { + desiredVSyncInterval = 0; + } + if (PSP_CoreParameter().fpsLimit != FPSLimit::NORMAL) { + int limit = PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 ? g_Config.iFpsLimit1 : g_Config.iFpsLimit2; + // For an alternative speed that is a clean factor of 60, the user probably still wants vsync. + if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) { + desiredVSyncInterval = 0; + } + } + + if (desiredVSyncInterval != lastVsync_ || force) { + // Disabled EXT_swap_control_tear for now, it never seems to settle at the correct timing + // so it just keeps tearing. Not what I hoped for... (gl_extensions.EXT_swap_control_tear) + // See http://developer.download.nvidia.com/opengl/specs/WGL_EXT_swap_control_tear.txt + gfxCtx_->SwapInterval(desiredVSyncInterval); + lastVsync_ = desiredVSyncInterval; + } +#endif +} + int GPUCommon::EstimatePerVertexCost() { // TODO: This is transform cost, also account for rasterization cost somehow... although it probably // runs in parallel with transform. diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index ff7236fb9192..17681cc55eeb 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -276,6 +276,7 @@ class GPUCommon : public GPUInterface, public GPUDebugInterface { } void BeginFrame() override; + void UpdateVsyncInterval(bool force); virtual void FastRunLoop(DisplayList &list); @@ -362,6 +363,10 @@ class GPUCommon : public GPUInterface, public GPUDebugInterface { // Debug stats. double timeSteppingStarted_; double timeSpentStepping_; + +#ifdef _WIN32 + int lastVsync_; +#endif }; struct CommonCommandTableEntry { diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 3f20ec064210..2bb2bb33f6b7 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -57,7 +57,6 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) drawEngine_(vulkan_, draw), depalShaderCache_(draw, vulkan_), vulkan2D_(vulkan_) { - UpdateVsyncInterval(true); CheckGPUFeatures(); shaderManagerVulkan_ = new ShaderManagerVulkan(draw, vulkan_); @@ -419,10 +418,6 @@ void GPU_Vulkan::InitClear() { } } -void GPU_Vulkan::UpdateVsyncInterval(bool force) { - // TODO -} - void GPU_Vulkan::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { GPUDebug::NotifyDisplay(framebuf, stride, format); framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index bb2efe587706..d1c10c537012 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -80,7 +80,6 @@ class GPU_Vulkan : public GPUCommon { void InitClear() override; void CopyDisplayToOutput() override; void Reinitialize() override; - inline void UpdateVsyncInterval(bool force); void InitDeviceObjects(); void DestroyDeviceObjects(); diff --git a/ext/native/gfx/d3d9_state.cpp b/ext/native/gfx/d3d9_state.cpp index fe7849b894e6..14887f7f1767 100644 --- a/ext/native/gfx/d3d9_state.cpp +++ b/ext/native/gfx/d3d9_state.cpp @@ -73,9 +73,6 @@ void CheckGLExtensions() { memset(&gl_extensions, 0, sizeof(gl_extensions)); } -void DirectXState::SetVSyncInterval(int interval) { -} - } // namespace DX9 #endif // _MSC_VER diff --git a/ext/native/gfx/d3d9_state.h b/ext/native/gfx/d3d9_state.h index 3304c22a1e81..a15683451717 100644 --- a/ext/native/gfx/d3d9_state.h +++ b/ext/native/gfx/d3d9_state.h @@ -484,9 +484,6 @@ class DirectXState { DxSampler0State1 texMaxMipLevel; DxSampler0State1 texAddressU; DxSampler0State1 texAddressV; - - // Only works on Win32, all other platforms are "force-vsync" - void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games) }; #undef STATE1 From 2a3fd05651df874f5a0f1ed149dff0c203687ca2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 29 Feb 2020 22:45:18 -0800 Subject: [PATCH 2/4] Vulkan: Present using FIFO for vsync. This allows the setting to be changed at runtime in Vulkan too. Should help #10105. --- Common/Vulkan/VulkanContext.cpp | 21 +++++++++------------ Common/Vulkan/VulkanContext.h | 2 ++ Core/HLE/sceDisplay.cpp | 7 ++++++- UI/GameSettingsScreen.cpp | 6 +++++- Windows/GPU/WindowsVulkanContext.cpp | 15 +++++++++++---- Windows/MainWindowMenu.cpp | 1 + android/jni/AndroidVulkanContext.cpp | 11 +++++++++-- 7 files changed, 43 insertions(+), 20 deletions(-) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index cb4dc0b33a09..ca1e5dec19c4 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -949,20 +949,17 @@ bool VulkanContext::InitSwapchain() { ILOG("Supported present mode: %d (%s)", presentModes[i], PresentModeString(presentModes[i])); } for (size_t i = 0; i < presentModeCount; i++) { - if (swapchainPresentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) { - // Default to the first present mode from the list. + bool match = false; + match = match || ((flags_ & VULKAN_FLAG_PRESENT_MAILBOX) && presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR); + match = match || ((flags_ & VULKAN_FLAG_PRESENT_FIFO_RELAXED) && presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR); + match = match || ((flags_ & VULKAN_FLAG_PRESENT_FIFO) && presentModes[i] == VK_PRESENT_MODE_FIFO_KHR); + match = match || ((flags_ & VULKAN_FLAG_PRESENT_IMMEDIATE) && presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR); + + // Default to the first present mode from the list. + if (match || swapchainPresentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) { swapchainPresentMode = presentModes[i]; } - if ((flags_ & VULKAN_FLAG_PRESENT_MAILBOX) && presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { - swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; - break; - } - if ((flags_ & VULKAN_FLAG_PRESENT_FIFO_RELAXED) && presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR) { - swapchainPresentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; - break; - } - if ((flags_ & VULKAN_FLAG_PRESENT_IMMEDIATE) && presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) { - swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + if (match) { break; } } diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index fccc3dc98e10..f08d883ceb9c 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -13,6 +13,7 @@ enum { VULKAN_FLAG_PRESENT_MAILBOX = 2, VULKAN_FLAG_PRESENT_IMMEDIATE = 4, VULKAN_FLAG_PRESENT_FIFO_RELAXED = 8, + VULKAN_FLAG_PRESENT_FIFO = 16, }; enum { @@ -136,6 +137,7 @@ class VulkanContext { VkDevice GetDevice() const { return device_; } VkInstance GetInstance() const { return instance_; } uint32_t GetFlags() const { return flags_; } + void UpdateFlags(uint32_t flags) { flags_ = flags; } VulkanDeleteList &Delete() { return globalDeleteList_; } diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 972e2e759fe4..41834a7f334c 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -553,7 +553,12 @@ static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) { // we have nothing to do here. bool doFrameSkip = g_Config.iFrameSkip != 0; - if (!throttle && g_Config.bFrameSkipUnthrottle) { + bool unthrottleNeedsSkip = g_Config.bFrameSkipUnthrottle; + if (g_Config.bVSync && GetGPUBackend() == GPUBackend::VULKAN) { + // Vulkan doesn't support the interval setting, so we force frameskip. + unthrottleNeedsSkip = true; + } + if (!throttle && unthrottleNeedsSkip) { doFrameSkip = true; skipFrame = true; if (numSkippedFrames >= 7) { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index a6fae59fa451..4cdec193e6ba 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -342,7 +342,11 @@ void GameSettingsScreen::CreateViews() { #endif #ifdef _WIN32 - graphicsSettings->Add(new CheckBox(&g_Config.bVSync, gr->T("VSync"))); + CheckBox *vSync = graphicsSettings->Add(new CheckBox(&g_Config.bVSync, gr->T("VSync"))); + vSync->OnClick.Add([=](EventParams &e) { + NativeResized(); + return UI::EVENT_CONTINUE; + }); #endif CheckBox *hwTransform = graphicsSettings->Add(new CheckBox(&g_Config.bHardwareTransform, gr->T("Hardware Transform"))); diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index 7797b58289a5..772d03798997 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -74,6 +74,15 @@ static VulkanContext *g_Vulkan; static VulkanLogOptions g_LogOptions; +static uint32_t FlagsFromConfig() { + uint32_t flags = 0; + flags = g_Config.bVSync ? VULKAN_FLAG_PRESENT_FIFO : VULKAN_FLAG_PRESENT_MAILBOX; + if (g_validate_) { + flags |= VULKAN_FLAG_VALIDATE; + } + return flags; +} + bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_message) { *error_message = "N/A"; @@ -100,10 +109,7 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m VulkanContext::CreateInfo info{}; info.app_name = "PPSSPP"; info.app_ver = gitVer.ToInteger(); - info.flags = VULKAN_FLAG_PRESENT_MAILBOX; - if (g_validate_) { - info.flags |= VULKAN_FLAG_VALIDATE; - } + info.flags = FlagsFromConfig(); if (VK_SUCCESS != g_Vulkan->CreateInstance(info)) { *error_message = g_Vulkan->InitError(); delete g_Vulkan; @@ -184,6 +190,7 @@ void WindowsVulkanContext::Resize() { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); g_Vulkan->DestroyObjects(); + g_Vulkan->UpdateFlags(FlagsFromConfig()); g_Vulkan->ReinitSurface(); g_Vulkan->InitObjects(); diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 225e3ce681ba..32861c90f221 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -739,6 +739,7 @@ namespace MainWindow { case ID_OPTIONS_VSYNC: g_Config.bVSync = !g_Config.bVSync; + NativeResized(); break; case ID_OPTIONS_FRAMESKIP_AUTO: diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index 71c63077b6b0..1ff51b5f6773 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -81,6 +81,13 @@ AndroidVulkanContext::~AndroidVulkanContext() { g_Vulkan = nullptr; } +static uint32_t FlagsFromConfig() { + if (g_Config.bVSync) { + return VULKAN_FLAG_PRESENT_FIFO; + } + return VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED; +} + bool AndroidVulkanContext::InitAPI() { ILOG("AndroidVulkanContext::Init"); init_glslang(); @@ -105,7 +112,7 @@ bool AndroidVulkanContext::InitAPI() { VulkanContext::CreateInfo info{}; info.app_name = "PPSSPP"; info.app_ver = gitVer.ToInteger(); - info.flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED; + info.flags = FlagsFromConfig(); VkResult res = g_Vulkan->CreateInstance(info); if (res != VK_SUCCESS) { ELOG("Failed to create vulkan context: %s", g_Vulkan->InitError().c_str()); @@ -216,7 +223,7 @@ void AndroidVulkanContext::Resize() { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); g_Vulkan->DestroyObjects(); - // backbufferResize updated these values. TODO: Notify another way? + g_Vulkan->UpdateFlags(FlagsFromConfig()); g_Vulkan->ReinitSurface(); g_Vulkan->InitObjects(); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); From 6f86b6fdbef655c9c9959bb421d6cf1ba4187330 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 29 Feb 2020 22:47:08 -0800 Subject: [PATCH 3/4] D3D11: Respect vsync setting. Fixes #12493. --- Windows/GPU/D3D11Context.cpp | 4 ++-- Windows/GPU/D3D11Context.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index c8911e51442e..31b3bcb08673 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -42,12 +42,12 @@ D3D11Context::~D3D11Context() { } void D3D11Context::SwapBuffers() { - swapChain_->Present(0, 0); + swapChain_->Present(swapInterval_, 0); draw_->HandleEvent(Draw::Event::PRESENTED, 0, 0, nullptr, nullptr); } void D3D11Context::SwapInterval(int interval) { - // Dummy + swapInterval_ = interval; } HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) { diff --git a/Windows/GPU/D3D11Context.h b/Windows/GPU/D3D11Context.h index 88f1547295af..07d551b7ded7 100644 --- a/Windows/GPU/D3D11Context.h +++ b/Windows/GPU/D3D11Context.h @@ -67,4 +67,5 @@ class D3D11Context : public WindowsGraphicsContext { HMODULE hD3D11; int width; int height; + int swapInterval_ = 0; }; From bc90faebf70b996c31a01b9210056fa6b5c7c92c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 29 Feb 2020 22:48:32 -0800 Subject: [PATCH 4/4] D3D9: Allow vsync change at runtime. --- Windows/GPU/D3D9Context.cpp | 11 +++++++---- Windows/GPU/D3D9Context.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Windows/GPU/D3D9Context.cpp b/Windows/GPU/D3D9Context.cpp index 4317fd13285e..2ea38836e024 100644 --- a/Windows/GPU/D3D9Context.cpp +++ b/Windows/GPU/D3D9Context.cpp @@ -56,7 +56,7 @@ static void GetRes(HWND hWnd, int &xres, int &yres) { } void D3D9Context::SwapInterval(int interval) { - // Dummy + swapInterval_ = interval; } bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { @@ -159,7 +159,7 @@ bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { presentParams_.hDeviceWindow = wnd; presentParams_.EnableAutoDepthStencil = true; presentParams_.AutoDepthStencilFormat = D3DFMT_D24S8; - presentParams_.PresentationInterval = (g_Config.bVSync) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + presentParams_.PresentationInterval = swapInterval_ == 1 ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; if (has9Ex_) { if (windowed && IsWin7OrLater()) { @@ -205,16 +205,19 @@ void D3D9Context::Resize() { // This should only be called from the emu thread. int xres, yres; GetRes(hWnd_, xres, yres); + uint32_t newInterval = swapInterval_ == 1 ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;; bool w_changed = presentParams_.BackBufferWidth != xres; bool h_changed = presentParams_.BackBufferHeight != yres; + bool i_changed = presentParams_.PresentationInterval != newInterval; - if (device_ && (w_changed || h_changed)) { + if (device_ && (w_changed || h_changed || i_changed)) { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr); presentParams_.BackBufferWidth = xres; presentParams_.BackBufferHeight = yres; + presentParams_.PresentationInterval = newInterval; HRESULT hr = device_->Reset(&presentParams_); if (FAILED(hr)) { - // Had to remove DXGetErrorStringA calls here because dxerr.lib is deprecated and will not link with VS 2015. + // Had to remove DXGetErrorStringA calls here because dxerr.lib is deprecated and will not link with VS 2015. PanicAlert("Unable to reset D3D9 device"); } draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, 0, 0, nullptr); diff --git a/Windows/GPU/D3D9Context.h b/Windows/GPU/D3D9Context.h index 474137bb7dbc..9ad836d338d3 100644 --- a/Windows/GPU/D3D9Context.h +++ b/Windows/GPU/D3D9Context.h @@ -53,5 +53,6 @@ class D3D9Context : public WindowsGraphicsContext { HWND hWnd_; // Holds Our Window Handle HMODULE hD3D9_; D3DPRESENT_PARAMETERS presentParams_; + int swapInterval_ = 0; };