Fix mouse motion in VRR#12665
Conversation
|
Hello and thank you for making a PR to Hyprland! Please check the PR Guidelines and make sure your PR follows them. If your code can be tested, please always add tests. See more here. beep boop, I'm just a bot. A real human will review your PR soon. |
|
If this works for all locked/unlocked hw/sw wayland/xwayland combinations with different games then I'm happy that all the pointer skipping and movement accumulation gets nuked. The accumulation was needed because sending the movement with locked cursor to an xwayland client straight away caused and immediate frame event in return which was treated as a valid new frame from the game and broke VRR. |
aa771e7 to
466690d
Compare
|
I just checked and this definitely does not work correctly with software cursors. |
|
|
|
Two reasons for mouse motion scheduling frames when it shouldn't:
Admittedly that code is in need of some cleanup now, and I'm unsure if Also, maybe the better way is to do this in - if (!skipFrameSchedule)
+ if (!skipFrameSchedule && (!isMouseEvent || !monitor->shouldSkipScheduleFrameOnMouseEvent())) |
eeda66d to
c73e8c1
Compare
|
After more testing, the current status is (for things I tested):
|
|
First of all, thank you @Szwagi for digging deep into this, this is quite literally the only major show-stopper preventing me from gaming on Hyprland. Secondly, I'm not quite able to replicate your above behavior matrix. For me, no matter what, on the latest version of your branch, I'm seeing stuttery camera movement on CS2 with a frame limiter set, though perhaps there's something I'm missing. That being said, It looks like Half-Life 2 works for me with This seems like a real nightmare of an issue for you guys lol, if you want me to validate any further findings on my end let me know. |
|
Dunno if there's any relation, but last I checked, software cursors disable direct scanout regardless of if they're visible or not. Could direct scanout be related to the difference here? |
So I just re-tested this. With both direct scanout and hardware cursors enabled, playing Wayland native CS2 with an FPS limit of 140 on 144 VRR display, I'm still getting the occasional spike to 144 when moving the mouse, causing visible hitching. |
Can't reproduce on NVIDIA, could you share your config? Worth noting that CS2's Edit: |
Ah, I was unaware of that, switching to ManguHud's limiter did fix the issue on wayland. I think I'm still seeing the issue with CS2 in xwayland mode, though it is far less frequent. That being said, it feels amazing in Wayland. |
|
I am unsure if e4013b8 is entirely correct, but it should function the same or better than the frame schedule removed in ee471d1, and without introducing unnecessary frame schedules on mouse motion. From my testing it's only necessary for Firefox which seems to be broken (based on the amount of Firefox hacks)? It also fixes an issue with frames not being scheduled when the surface x/y is not on any monitor. I didn't look hard for the remaining hardware cursor issue yet, but I suspect it might be a bug in Aquamarine. Status to my eye:
|
|
I just pulled and did a test of my own with the 8 combinations when This even fixed the mild VRR flicker I was getting. Good job again on this one, you have no idea how much sanity I was losing testing things before I saw this PR. |
|
e60c987 fixes framerate spiking when changing window focus caused by animations scheduling many thousands of frames per second for animations that aren't visible. I did more research and I don't believe Hyprland is responsible for breaking VRR with hardware cursors and no_break_fs_vrr=1. With an unlocked cursor, Hyprland schedules exactly 125FPS on a 125FPS lock, but my monitor reports 250FPS or an unstable 330FPS coming in depending on the game. It's possible there's still an extra frame scheduled on cursor visibility change. My reports spikes by 1-2FPS, but I couldn't see any extra frame schedules except for the unrelated 37ae610, perhaps monitor getting confused by a lag spike in the game when opening the menu. @vaxerski I think this is all for the issues I found. I will now daily this branch to see if something comes up, but would like to know what you think of this and what the glaring issues are :D |
vaxerski
left a comment
There was a problem hiding this comment.
in general looks ok just needs some testing yea
|
i dont think aa533b8 is right, wont this damage the entire logicalbox on every single commit now and basicly ignore if any damage was actually sent? |
from the bits ive digged i think there is a frame callback issue in general in HL, ive tried doing something about it but im just not getting it 100% correct and the rabbits nest goes deep see #11454 , some clients like firefox seems to rely on it being sent on monitor pageflip pretty much. both for their vsync handling and for recieving hints on when to send the next buffer. currently its done on commit time and presentation. and eventually hits the renderer here Hyprland/src/render/Renderer.cpp Line 1442 in 42447a5 or it hits Hyprland/src/protocols/core/Compositor.cpp Line 656 in 42447a5 |
Since this is a bigger issue that others are looking into, and the frame schedule hack was already there before my changes, would it be acceptable to keep the hack (adjusted for what this PR is looking to solve) and resolve that at a different time? @vaxerski
Right... I didn't quite think that through. My intention was to only schedule a frame, not add damage. Does something like this make more sense? I think this is pretty much what it was 3 years ago (beef23c), just without some issues related to // schedule frame events (hack)
if (!WLSURF->resource()->m_current.callbacks.empty()) {
const auto VIEW = WLSURF->view();
const auto BOX = VIEW->logicalBox();
if (BOX.has_value() && !BOX->empty()) {
for (auto const& m : g_pCompositor->m_monitors) {
if (!m->m_output)
continue;
if (BOX->overlaps(m->logicalBox()))
g_pCompositor->scheduleFrameForMonitor(m, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME);
}
}
}
CRegion damageBox = WLSURF->computeDamage();
if (damageBox.empty())
return; |
something like that might work, as long as it doesnt show other regressions popping up because it was relying on that scheduled frame unintentionally |
|
I rebased it on main and it crashes on startup, did I do something wrong? Edit: Wrong stack trace |
2826e26 to
4131c67
Compare
567cd8f to
9ccb4ae
Compare
|
Rebased it on current main. I initially wanted to implement 9ccb4ae by checking if any other monitor has VRR active, so it'd still use the hardware cursor in a lot of common cases. That ended up breaking VRR when the cursor was on the boundary between two monitors. I'll look into why that happens.
Do you have |
|
@vaxerski Opinion? Have been using this branch daily for desktop use and gaming (with and without VRR). I didn't encounter any more issues on NVIDIA. Things to note:
Not perfect, but significantly more usable for gaming than before. Potentially ready to merge? |
9ccb4ae to
d31f396
Compare
maximized windows' border animation causes repaint artifacts |
|
Seems I was wrong about my report on multi-monitor working fine on AMD. It works fine if I disable my secondary monitor. Software cursors don't fix it. EDIT: This is using native Wayland. Gamescope cursor capture doesn't have this issue, nor does native Wayland under Sway. |
|
When I get out of bed I’m gonna test it on multi-monitor AMD setup. |
|
I have two monitors, one 165hz, main one the game is on 240hz. Edit: I don't know accurate my monitor OSD is and such, so take with bit of salt, seems finicky. |
|
Hm, it does look direct scanout related. At least with Sorry, false alarm. I might be seeing a form of #12423 |
|
DS and tearing shouldn't affect this directly. They just have different sw/hw cursors requirements. |
| case 0: return false; | ||
| case 1: return true; | ||
| case 2: return g_pHyprRenderer->isNvidia() && g_pHyprRenderer->isMgpu(); | ||
| case 2: return g_pHyprRenderer->isNvidia() && (g_pHyprRenderer->isMgpu() || g_pCompositor->isVRRActiveOnAnyMonitor()); |
There was a problem hiding this comment.
this check seems wrong to me.
if you have vrr=1 at all, then this will just force sw cursor all the time, it should only do it if vrr is active + fullscreen afaik
There was a problem hiding this comment.
this check seems wrong to me.
if you have vrr=1 at all, then this will just force sw cursor all the time, it should only do it if vrr is active + fullscreen afaik
On my setup moving a hardware cursor on the second monitor makes the VRR monitor go black (framerate spike switches mode to non-vrr for a second). That is not usable.
The condition could definitely be better (especially in case of 1 monitor).
I have tried switching to software cursor for the secondary monitor, but it's very pretty wonky on the edges of the monitors.
Ultimately I want to look into making hardware cursors work correctly on NVIDIA.
There was a problem hiding this comment.
Sorry to hear that your monitor modesets when going in and out of VRR, but that is definitely not the norm. This PR was also specific to fixing the variable no_break_fs_vrr which is specific to FS.
Anyway I've just set no hw cursor to 0 for now
There was a problem hiding this comment.
Sorry to hear that your monitor modesets when going in and out of VRR, but that is definitely not the norm. This PR was also specific to fixing the variable
no_break_fs_vrrwhich is specific to FS.Anyway I've just set no hw cursor to 0 for now
It was a thing on 2/2 ASUS monitors I owned, so I think it's pretty common. Not a very reputable brand so I'd believe if you said it's not a thing on others.
The PR ended up being about removing most instances of VRR breaking (not just the ones caused by removal of mouse input hack), that's why the hardware cursor check was added too... hopefully temporarily.
There was a problem hiding this comment.
AFAIK the AMDGPU driver behaves such that, when a display supports VRR, it's always sending a VRR signal. Even with VRR disabled, it just keeps the FPS locked at max, so it doesn't need to modeset.
NVIDIA probably doesn't do that. In which case it might be necessary to emulate that behavior within Hyprland.
There was a problem hiding this comment.
NVIDIA probably doesn't do that.
nvidia also does that unless you use a specific kernel param to outright disable vrr
I am unfamiliar with the codebase, so this PR most definitely has plenty of issues I haven't found.
If the actual solution is more complicated than this, I'm unlikely to be of any help, but would love to see this fixed and working as well as this is for me.
Fixes #12032 and this sounds related too #12013.
I will take CS2 on a 360Hz display as an example. When I say FPS measurements I mean what the monitor reports.
Before (the issues):
After:
My idea of what is happening is that
I have tested in CS2 with native Wayland and XWayland. I have also tested in a Wine game running through Gamescope.