Here is a patch which can be applied on top of the kwin package to include the two patches which modify GlxBackend::GlxBackend.
From ad5f05d207edd32fc8571c9ae6bb916e61b291d4 Mon Sep 17 00:00:00 2001 From: Charlemagne Lasse <charlemagnela...@gmail.com> Date: Tue, 26 Mar 2019 15:30:19 +0100 Subject: [PATCH] Fix missing vsync and high CPU load with Nvidia's proprietary driver
--- debian/changelog | 8 ++ .../patches/Fix-flickering-with-Qt-5.12.patch | 47 ++++++++++ ...pBuffers-to-block-with-NVIDIA-driver.patch | 94 +++++++++++++++++++ debian/patches/series | 2 + 4 files changed, 151 insertions(+) create mode 100644 debian/patches/Fix-flickering-with-Qt-5.12.patch create mode 100644 debian/patches/Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch diff --git a/debian/changelog b/debian/changelog index 0f0e4d3..4f4ce7b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +kwin (4:5.14.5-2) UNRELEASED; urgency=medium + + [ Charlemagne Lasse ] + * Backport upstream patches to fix missing vsync and high CPU load with + Nvidia's proprietary driver (Closes: #925528) + + -- Charlemagne Lasse <charlemagnela...@gmail.com> Tue, 26 Mar 2019 15:26:54 +0100 + kwin (4:5.14.5-1) unstable; urgency=medium * New upstream release (5.14.5). diff --git a/debian/patches/Fix-flickering-with-Qt-5.12.patch b/debian/patches/Fix-flickering-with-Qt-5.12.patch new file mode 100644 index 0000000..647fc69 --- /dev/null +++ b/debian/patches/Fix-flickering-with-Qt-5.12.patch @@ -0,0 +1,47 @@ +From: Alexander Volkov <a.vol...@rusbitech.ru> +Date: Tue, 22 Jan 2019 22:36:15 +0300 +Subject: Fix flickering with Qt 5.12 + +Summary: +Mesa requires XESetWireToEvent xlib callbacks to be called +when DRI2 is used. This is done by the GLX integration in +the Qt's xcb plugin, but Qt 5.12 initializes the GLX integration +only when required, e.g. when a window with OpenGL support is +created or when availability of OpenGL is checked. + +So force initialization of the GLX integration by calling +QOpenGLContext::supportsThreadedOpenGL(). + +https://codereview.qt-project.org/#/c/6557/ +https://bugzilla.opensuse.org/show_bug.cgi?id=1120090 + +Reviewers: #kwin, graesslin + +Reviewed By: #kwin, graesslin + +Subscribers: davidedmundson, graesslin, fvogt, filipf, kwin + +Tags: #kwin + +Differential Revision: https://phabricator.kde.org/D18366 + +Origin: upstream, https://cgit.kde.org/kwin.git/patch/?id=5d63b9c05bbe0c6545b3eeea98d95b40f800fb55 +--- + plugins/platforms/x11/standalone/glxbackend.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/plugins/platforms/x11/standalone/glxbackend.cpp b/plugins/platforms/x11/standalone/glxbackend.cpp +index a2c570e..eb2d464 100644 +--- a/plugins/platforms/x11/standalone/glxbackend.cpp ++++ b/plugins/platforms/x11/standalone/glxbackend.cpp +@@ -115,6 +115,10 @@ GlxBackend::GlxBackend(Display *display) + , haveSwapInterval(false) + , m_x11Display(display) + { ++ // Force initialization of GLX integration in the Qt's xcb backend ++ // to make it call XESetWireToEvent callbacks, which is required ++ // by Mesa when using DRI2. ++ QOpenGLContext::supportsThreadedOpenGL(); + } + + static bool gs_tripleBufferUndetected = true; diff --git a/debian/patches/Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch b/debian/patches/Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch new file mode 100644 index 0000000..97b5932 --- /dev/null +++ b/debian/patches/Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch @@ -0,0 +1,94 @@ +From: Erik Kurzinger <ekurzin...@nvidia.com> +Date: Wed, 20 Mar 2019 09:50:13 -0700 +Subject: Force glXSwapBuffers to block with NVIDIA driver + +Summary: +The NVIDIA implementation of glXSwapBuffers will, by default, queue up +to two frames for presentation before blocking. KWin's compositor, +however, assumes that calls to glXSwapBuffers will always block until +the next vblank when rendering double buffered. This assumption isn't +valid, as glXSwapBuffers is specified as being an implicit glFlush, +not an implicit glFinish, and so it isn't required to block. When this +assumption is violated, KWin's frame timing logic will +break. Specifically, there will be extraneous calls to +setCompositeTimer with a waitTime of 0 after the non-blocking buffer +swaps, dramatically reducing desktop responsiveness. To remedy this, +a call to glXWaitGL was added by Thomas Luebking after glXSwapBuffers +in 2015 (see bug 346275, commit +8bea96d7018d02dff9462326ca9456f48e9fe9fb). That glXWaitGL call is +equivalent to a glFinish call in direct rendering, so it was a good +way to make glXSwapBuffers behave as though it implied a glFinish +call. + +However, the NVIDIA driver will by default do a busy wait in glFinish, +for reduced latency. Therefore that change dramatically increased CPU +usage. GL_YIELD can be set to USLEEP (case insensitive) to change +the behavior and use usleep instead. When using the NVIDIA driver, +KWin will disable vsync entirely if GL_YIELD isn't set to USLEEP +(case sensitive, a bug in KWin). + +However, the NVIDIA driver supports another environment variable, +__GL_MaxFramesAllowed, which can be used to control how many frames +may be queued by glXSwapBuffers. If this is set to 1 the function +will always block until retrace, in line with KWin's expectations. +This allows the now-unnecessary call to glXWaitGL to be removed along +with the logic to conditionally disable vsync, providing a better +experience on NVIDIA hardware. + +Reviewers: #kwin, davidedmundson, zzag + +Reviewed By: #kwin, davidedmundson, zzag + +Subscribers: kwin, davidedmundson, zzag + +Tags: #kwin + +Differential Revision: https://phabricator.kde.org/D19867 + +Origin: upstream, https://cgit.kde.org/kwin.git/patch/?id=22a441e071515e9c630f3bdac743c678052f88be +--- + plugins/platforms/x11/standalone/glxbackend.cpp | 22 +++++----------------- + 1 file changed, 5 insertions(+), 17 deletions(-) + +diff --git a/plugins/platforms/x11/standalone/glxbackend.cpp b/plugins/platforms/x11/standalone/glxbackend.cpp +index eb2d464..70dba60 100644 +--- a/plugins/platforms/x11/standalone/glxbackend.cpp ++++ b/plugins/platforms/x11/standalone/glxbackend.cpp +@@ -115,6 +115,11 @@ GlxBackend::GlxBackend(Display *display) + , haveSwapInterval(false) + , m_x11Display(display) + { ++ // Ensures calls to glXSwapBuffers will always block until the next ++ // retrace when using the proprietary NVIDIA driver. This must be ++ // set before libGL.so is loaded. ++ setenv("__GL_MaxFramesAllowed", "1", true); ++ + // Force initialization of GLX integration in the Qt's xcb backend + // to make it call XESetWireToEvent callbacks, which is required + // by Mesa when using DRI2. +@@ -696,25 +701,8 @@ void GlxBackend::present() + glXWaitGL(); + if (char result = m_swapProfiler.end()) { + gs_tripleBufferUndetected = gs_tripleBufferNeedsDetection = false; +- if (result == 'd' && GLPlatform::instance()->driver() == Driver_NVidia) { +- // TODO this is a workaround, we should get __GL_YIELD set before libGL checks it +- if (qstrcmp(qgetenv("__GL_YIELD"), "USLEEP")) { +- options->setGlPreferBufferSwap(0); +- setSwapInterval(0); +- result = 0; // hint proper behavior +- qCWarning(KWIN_X11STANDALONE) << "\nIt seems you are using the nvidia driver without triple buffering\n" +- "You must export __GL_YIELD=\"USLEEP\" to prevent large CPU overhead on synced swaps\n" +- "Preferably, enable the TripleBuffer Option in the xorg.conf Device\n" +- "For this reason, the tearing prevention has been disabled.\n" +- "See https://bugs.kde.org/show_bug.cgi?id=322060\n"; +- } +- } + setBlocksForRetrace(result == 'd'); + } +- } else if (blocksForRetrace()) { +- // at least the nvidia blob manages to swap async, ie. return immediately on double +- // buffering - what messes our timing calculation and leads to laggy behavior #346275 +- glXWaitGL(); + } + } else { + waitSync(); diff --git a/debian/patches/series b/debian/patches/series index 01a57e3..b0da0e0 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,5 @@ Disable-testShadeWobblyWindows.patch Ignore-cursor-weird-behaviour-under-a-containerized-xvfb.patch disable-MouseMark-and-TrackMouse-effects-loading-test.patch +Fix-flickering-with-Qt-5.12.patch +Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch -- 2.20.1