Bug#925528: kwin-x11: High CPU load and extreme screen tearing with nvidia driver
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 <charlemagnelasse@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 <charlemagnelasse@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.volkov@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 <ekurzinger@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
Reply to: