swaywm / sway

i3-compatible Wayland compositor
https://swaywm.org
MIT License
14.77k stars 1.11k forks source link

Adaptive sync / variable refresh broken when fullscreen #7370

Open phaserblast opened 1 year ago

phaserblast commented 1 year ago

Adaptive sync seems to be broken when going fullscreen on the Intel modesetting driver (kernel 6.1.3). When nothing is fullscreen, adaptive sync works and my FreeSync display reports the correct variable refresh rate. In fact, the display will sync correctly when there's only one thing being rendered via OpenGL in a single panel. However, as soon as an application goes fullscreen, the display changes to its default refresh rate (in my case, 75Hz) and ignores the variable timing. When running on a real X server and not sway, everything works fine so it's not my system. The only workaround I've found is to launch sway setting the WLR_DRM_NO_ATOMIC=1 variable, however this only fixes apps that are Wayland native (X apps using Xwayland still won't work with adaptive sync even with the workaround). For example, launching MAME using -videodriver wayland works with the above workaround, however launching in X11 mode gets no adaptive sync.

abigrock commented 1 year ago

This may be a duplicate of Issue 5601. So far launching sway via sway -Dnoscanout or by setting the variable WLR_DRM_NO_MODIFIERS=1 before launching sway fixes fullscreen adaptive sync with Xwayland applications for me. Both have their own drawbacks however.

phaserblast commented 1 year ago

This may be a duplicate of Issue 5601. So far launching sway via sway -Dnoscanout or by setting the variable WLR_DRM_NO_MODIFIERS=1 before launching sway fixes fullscreen adaptive sync with Xwayland applications for me. Both have their own drawbacks however.

Thanks. Setting WLR_DRM_NO_MODIFIERS=1 worked on my system with Intel graphics. Variable sync seems to be work with both Wayland and X applications. Can you elaborate on the drawbacks of this? I'm not even sure exactly what setting this variable does.

abigrock commented 1 year ago

Thanks. Setting WLR_DRM_NO_MODIFIERS=1 worked on my system with Intel graphics. Variable sync seems to be work with both Wayland and X applications. Can you elaborate on the drawbacks of this? I'm not even sure exactly what setting this variable does.

Issue 5601 has a couple of explanations about the drawbacks for WLR_DRM_NO_MODIFIERS and -Dnoscanout. See here and here.

rhoot commented 1 year ago

I have yet to try any of the flags here, but I noticed yesterday: If adaptive sync doesn't work when fullscreened (it seems like a 50/50 thing), using swaymsg to toggle it off and on again from another monitor/workspace appears to fix it.

plasmamax1 commented 1 year ago

I am also noticing this issue. Fullscreen Xwayland apps will stop adaptive sync while fullscreen wayland apps are able to continue using adaptive sync. Setting "WLR_DRM_NO_MODIFIERS=1" allows Xwayland apps to use adaptive sync while fullscreen.

GrabbenD commented 1 year ago

FIY this made no difference as the monitor is stuck at a fixed refresh rate on AW3821DW with RX 6800 XT and it doesn't matter if the game is in fullscreen mode or not:

export WLR_DRM_NO_MODIFIERS=1
dbus-run-session sway

However, this works as VRR starts to function properly by matching monitor's refresh rate to FPS:

dbus-run-session sway -Dnoscanout

_(P.S. don't use dbus-run-session with Arch Linux)_

I've tried it multiple times to be sure!

GrabbenD commented 1 year ago

I can consistently reproduce this issue not just in Sway but also with other compositors like Gamescope, RiverVM and Hyprland. I've made a new issue report: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3721

phaserblast commented 1 year ago

However, this works as VRR starts to function properly:

dbus-run-session sway -Dnoscanout

I've tried it multiple times to be sure!

Since you're using AMD graphics you ~have the option to force the kernel driver into VRR mode (no way to do this on Intel as far as I know). You can set this kernel param in your boot config: amdgpu.freesync_video=1 This is a good troubleshooting tool.~ The only other way to ensure VRR is enabled on a CRTC is to set the VRR_ENABLED property manually using the DRM interface, which I think can be done with the 'modetest' program (modetest.c). There was another comment here saying there was a "50/50" chance VRR worked, and the reason for this intermittent success is most likely VRR being toggled off in the modesetting driver by default at boot. If VRR is toggled off on the CRTC, then there's no point in trying to troubleshoot as nothing you do will make it work until the VRR property is turned on.

Edit: see below for what amdgpu.freesync_video=1 actually does.

rhoot commented 1 year ago

There was another comment here saying there was a "50/50" chance VRR worked, and the reason for this intermittent success is most likely VRR being toggled off in the modesetting driver by default at boot.

That was me. It still does seem like a 50/50 thing, but only seems to affect direct scan out for me as well. Disabling it (launching sway with -Dnoscanout) makes it work very reliably all the time. Would you still suspect a modesetting issue?

GrabbenD commented 7 months ago

Adaptive Sync is still problematic 🙁


KDE recently made a few bugfixes (around stuttering/flickering) with Adaptive Sync. These fixes are related to Direct Scanout https://invent.kde.org/plasma/kwin/-/merge_requests/5626

GrabbenD commented 3 weeks ago

You can set this kernel param in your boot config: amdgpu.freesync_video=1

According to amdgpu developers, amdgpu.freesync_video=1 isn't supposed to be used for gaming but rather embedded systems which stream video. The consequence of using this might be increased blanking

amdgpu.freesync_video changelog:

phaserblast commented 3 weeks ago

According to amdgpu developers, amdgpu.freesync_video isn't supposed to be used for gaming but rather embedded systems which stream video. The consequence of using this might be increased blanking

Okay, I looked at the source for amdgpu_drv.c and here's what the parameter freesync_video does:

Setting freesync_video to 1 tells the amdgpu driver to make up some phony fixed video modes based on the current supported variable refresh range, even if these discrete modes aren't reported by the display. These are "fake" video modes, but they work anyway because... hey, VRR. These modes use typical film/video timings like 48Hz, 50Hz and 72Hz. This allows an application with an old-school render loop to change the video mode to one that is better suited for film playback (24/25fps). Since these modes aren't "real," there shouldn't be any display hiccups during a mode change as these modes are implemented using VRR.

However, this is all kinda silly because NTSC rates will never snap perfectly to 48.00, 60.00 or 72.00Hz so audio sync will fail over time and/or frames will get dropped, negating the whole idea. I guess these modes exist if the application render loop needs to be synced to the display refresh rate, but doing this in 2024 is just lazy software design and audio sync still won't work. We live in a world where VRR displays are becoming more commonplace, and so the application should be triggering the refresh itself using DRM calls and not rely on a fixed rate as this feature provides. Why lock yourself to only 72Hz when you already have total control over the refresh rate? And with more people shooting professional YouTube videos on iPhones that always shoot variable FPS, it makes more sense to just use "normal" VRR, and render using the traditional EGL+DRM technique because a VRR display is the only way to ensure perfect presentation of a variable FPS video. I'm pretty sure the days of genlocking the render loop to the display refresh rate are over.

So you may as well just set freesync_video=0. It's pointless. You stll need to enable the VRR property on the CRTC for VRR to work. I use KDE plasma, and it does this automatically when an application goes fullscreen.