[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#925528: kwin-x11: High CPU load and extreme screen tearing with nvidia driver



Package: kwin-x11
Version: 4:5.14.5-1
Severity: important
Tags: buster sid patch upstream fixed-upstream
Forwarded: https://bugs.kde.org/show_bug.cgi?id=322060

kwin-x11 with the current nvidia driver causes extreme high CPU load
and tearing. The graphics performance is also reduced to an
unacceptable level when compositing is enabled. This is caused by the
way how kwin-x11 tries to flush frames - which doesn't work with
advanced drivers (like the ones from nvidia). This was better
described by Erik Kurzinger in his patch
https://phabricator.kde.org/D19867

    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.

The patch can be found under https://phabricator.kde.org/D19867 and
upstream (Martin Flöser) recommends to backport it to all older
versions. This also includes Debian Buster (and maybe also Stretch -
not sure about this part)


Reply to: