From 2a438d6e03958369240eb67bc22987a47c437230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Mar 2018 20:07:31 +0100 Subject: [PATCH] Fix VSync on Windows. Should fix #10711 --- Windows/GPU/WindowsGLContext.cpp | 15 +++++++++------ ext/native/thin3d/GLRenderManager.cpp | 6 ++++++ ext/native/thin3d/GLRenderManager.h | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 7bed8d1e69..8feae44307 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -332,8 +332,6 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { hRC = m_hrc; - SwapInterval(0); - if (g_Config.bGfxDebugOutput) { if (wglewIsSupported("GL_KHR_debug") == 1) { glGetError(); @@ -375,16 +373,21 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); SetGPUBackend(GPUBackend::OPENGL); bool success = draw_->CreatePresets(); // if we get this far, there will always be a GLSL compiler capable of compiling these. - renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); }); assert(success); + renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); }); + if (wglSwapIntervalEXT) { + // glew loads wglSwapIntervalEXT if available + renderManager_->SetSwapIntervalFunction([&](int interval) { + wglSwapIntervalEXT(interval); + }); + } CHECK_GL_ERROR_IF_DEBUG(); return true; // Success } void WindowsGLContext::SwapInterval(int interval) { - // glew loads wglSwapIntervalEXT if available - if (wglSwapIntervalEXT) - wglSwapIntervalEXT(interval); + // Delegate to the render manager to make sure it's done on the right thread. + renderManager_->SwapInterval(interval); } void WindowsGLContext::Shutdown() { diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index e126fd34e8..31e571c295 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -436,6 +436,12 @@ void GLRenderManager::EndSubmitFrame(int frame) { Submit(frame, true); if (!frameData.skipSwap) { + if (swapIntervalChanged_) { + swapIntervalChanged_ = false; + if (swapIntervalFunction_) { + swapIntervalFunction_(swapInterval_); + } + } if (swapFunction_) { swapFunction_(); } diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 11b93dafd9..5cb4e54e61 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -682,6 +682,7 @@ public: void RegisterPushBuffer(int frame, GLPushBuffer *buffer) { frameData_[frame].activePushBuffers.insert(buffer); } + void UnregisterPushBuffer(int frame, GLPushBuffer *buffer) { auto iter = frameData_[frame].activePushBuffers.find(buffer); _assert_(iter != frameData_[frame].activePushBuffers.end()); @@ -692,6 +693,17 @@ public: swapFunction_ = swapFunction; } + void SetSwapIntervalFunction(std::function swapIntervalFunction) { + swapIntervalFunction_ = swapIntervalFunction; + } + + void SwapInterval(int interval) { + if (interval != swapInterval_) { + swapInterval_ = interval; + swapIntervalChanged_ = true; + } + } + void StopThread(); bool SawOutOfMemory() { @@ -765,8 +777,12 @@ private: int curFrame_ = 0; std::function swapFunction_; + std::function swapIntervalFunction_; GLBufferStrategy bufferStrategy_ = GLBufferStrategy::SUBDATA; + int swapInterval_ = 0; + bool swapIntervalChanged_ = true; + int targetWidth_ = 0; int targetHeight_ = 0; };