https://bugs.kde.org/show_bug.cgi?id=525619

            Bug ID: 525619
           Summary: Stuttering in fixed rate screencast session with Kwin
                    6.7.90.
    Classification: Plasma
           Product: kwin
      Version First 6.7.90
       Reported In:
          Platform: Arch Linux
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: screencasting
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

DESCRIPTION
Stuttering in fixed rate (maxFramerate = 60/1) screencast session with KWin
6.7.90. Issue was not present in KWin 6.7.4 just prior to upgrading to the beta
version via Arch's kde-unstable repo.

STEPS TO REPRODUCE - PREREQUISITES
Host configuration: physical/virtual display configured for 60Hz, 1080P.
Client configuration: select 60fps for stream in Moonlight.
Game configuration: start with vsync enabled, 60 fps in-game limit. Testing
requires FPS to fall below the screen refresh interval, so make sure that
toggling the FPS limit in the game actually changes in realtime.

STEPS TO REPRODUCE
1. Install a patched[1] build of Sunshine and use `portal` or `kwin` capture
2. Start a game that supports VSync and in-game realtime FPS limiting. Resident
Evil Requiem Demo should work, as an example. 
3. Observe smoothness by panning the in-game camera.
4. Enter menu, select 30 fps, wait a few seconds, select 60fps, and return to
the game and immediately pan the camera to observe smoothness.

OBSERVED RESULT
Almost every time I toggle 60 -> 30 -> 60fps, there is intermittent stuttering
that can take tens of seconds to resolve. This stuttering also happens randomly
in-game without specifically toggling the FPS; I presume it happens when
there's a 1% low that falls under the vblank rate.

EXPECTED RESULT
Smooth stream when 60fps configured in-game.

SOFTWARE/OS VERSIONS
Operating System: Arch Linux
KDE Plasma Version: 6.7.90
KDE Frameworks Version: 6.30.0
Qt Version: 6.12.0
Kernel Version: 7.2.4-zen2-1-zen (64-bit)
Graphics Platform: Wayland
Processors: 16 × AMD Ryzen 7 5700X 8-Core Processor
Memory: 24 GiB of RAM (23.4 GiB usable)
Graphics Processor: AMD Radeon RX 6600

BISECTION:
I bisected the regression to:
e29d8f841220cba2daf501e50dfa32ee335961d9 wayland: support the commit-timing
protocol

WORKAROUNDS TESTED:
1. Disabling vsync in-game resolves the issue.
2. Running Sunshine in variable rate capture mode (maxFramerate negotiated to
0/1) doesn't seem to have this issue, or at the very least, prevents the
specific test case from triggering the stuttering so easily. Changing
Sunshine's behaviour to negotiate variable rate is not a perfect fix, however,
as KWin since 6.7.x has incorrect desktop animation speeds if we use variable
rate capture.
3. `VKD3D_DISABLE_EXTENSIONS=VK_KHR_present_timing %command%` did not resolve
the issue when vsync is enabled.
4. Patching vkd3d-proton [2] to disable functions that looked to be related,
with or without `VK_KHR_present_timing` disabled, didn't help.

ADDITIONAL INFORMATION
[1] Sunshine on master branch currently selects fixed rate (maxFramerate =
framerate / 1) based on a simple version check for KWin 6.8, but it doesn't
handle the beta versioning. It requires this change to enable fixed rate on the
beta versions:
```
diff --git a/src/platform/linux/pipewire.cpp b/src/platform/linux/pipewire.cpp
index fc7c63d2..79ef8520 100644
--- a/src/platform/linux/pipewire.cpp
+++ b/src/platform/linux/pipewire.cpp
@@ -848,7 +848,7 @@ namespace pipewire {
       // Ref: https://bugs.kde.org/show_bug.cgi?id=524129
       // Also negotiate variable rate for all other compositors. Mutter's
variable rate pacing is superior.
       const static std::vector<int> kwin_version = get_running_kwin_version();
-      const static bool negotiate_variable_rate = kwin_version.empty() ||
(kwin_version[0] == 5 || (kwin_version[0] == 6 && kwin_version[1] < 8));
+      const static bool negotiate_variable_rate = kwin_version.empty() ||
(kwin_version[0] == 5 || (kwin_version[0] == 6 && kwin_version[1] < 8 &&
kwin_version[2] < 80));

       const AVRational fps = (negotiate_variable_rate ? AVRational {0, 1} :
::video::framerate_to_rational(config));
       if (fps.den != 1) {
```
2. Quick hack against vkd3d-proton used for single test case:
```
diff --git a/libs/vkd3d/swapchain.c b/libs/vkd3d/swapchain.c
index 7140f6c8..1a70c58f 100644
--- a/libs/vkd3d/swapchain.c
+++ b/libs/vkd3d/swapchain.c
@@ -55,24 +55,26 @@ static inline bool vkd3d_swapchain_present_mode_parse(const
char *string, VkPres

 static inline bool present_mode_pacing_should_wait(VkPresentModeKHR
present_mode)
 {
     /* FIFO_LATEST_READY is intentionally excluded. Unlike FIFO and
FIFO_RELAXED,
      * it does not block on Vsync boundaries and present-wait would not
provide
      * meaningful backpressure. When VK_EXT_present_timing becomes available,
      * VkPresentTimingInfoEXT.targetTime would be the appropriate pacing
mechanism.
      */
+    return false;
     return present_mode == VK_PRESENT_MODE_FIFO_KHR ||
            present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR;
 }

 static inline bool present_mode_supports_timing(VkPresentModeKHR present_mode,
uint32_t interval)
 {
     /* If app wants to run unlocked we shouldn't be using timing.
      * The basic idea behind LATEST_READY is that it's somewhat of a flexible
hybrid of mailbox and FIFO. */
+    return false;
     return present_mode == VK_PRESENT_MODE_FIFO_KHR ||
             present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR ||
             (present_mode == VK_PRESENT_MODE_FIFO_LATEST_READY_KHR &&
interval);
 }

 static inline struct dxgi_vk_swap_chain_factory
*impl_from_IDXGIVkSwapChainFactory(IDXGIVkSwapChainFactory *iface)
 {
     return CONTAINING_RECORD(iface, struct dxgi_vk_swap_chain_factory,
IDXGIVkSwapChainFactory_iface);
```

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to