Repository navigation
Conversation
Read pending raw input in one go with GetRawInputBuffer and hand the game one merged WM_INPUT per message pump pass, so 4000/8000 Hz mice no longer keep the pump busy for most of the frame. Signed-off-by: alva98 <59375624+xalva98@users.noreply.github.com>
fivem-mouse-lag.mp4small video to demonstrate the issue; moving your mouse ingame with 8000hz input drops your fps in half, and on minimap from 300 to 20-30 sometimes |
|
Built this locally and can confirm it fixes it here too. 8000 Hz camera movement went from 42-54 fps to 360-420 (7800X3D, RX 9070 XT, Logitech Pro X Superstrike). There was still a gap to 1000 Hz, which turned out to be the legacy mouse messages Windows generates for every report. I opened a small PR on your branch that sets RIDEV_NOLEGACY while the game owns the mouse. That gets 8000 Hz to ~490 fps vs ~530 at 1000 Hz: xalva98#1 |
…the mouse (#1) With 4000/8000 Hz mice Windows generates WM_MOUSEMOVE/WM_SETCURSOR/WM_NCHITTEST for every raw report, which made PeekMessage cost ~0.5 ms per frame even with batched raw input reads. Register the mouse with RIDEV_NOLEGACY while the game window is active and neither the console nor a NUI frame needs the cursor (including SetNuiFocusKeepInput). Configurable via in_mouseNoLegacy. Also reset the raw input pass flag every frame so a pump pass that ends early can't hold back input in the next frame. Signed-off-by: OneEarJoe5 <212275319+OneEarJoe5@users.noreply.github.com>
|
The NOLEGACY part broke the "Windows Input" mouse method (no camera movement on a fresh start). Fixed in a follow-up on the branch, which also gets Windows Input to ~480 fps at 8000 Hz instead of 40-60: xalva98#2 |
* fix(rage-input-five): fix the "Windows Input" mouse method NOLEGACY broke the "Windows Input" mouse method, the camera didn't react until you changed the mouse method in the settings once. That mode gets its moves and clicks from the legacy messages, so NOLEGACY is only used for raw input now. While testing that I noticed "Windows Input" still drops to 40-60 fps with an 8000 Hz mouse, because the game handles one WM_MOUSEMOVE per report. For the non-raw methods the pump pass now also ends after the first WM_MOUSEMOVE. Buttons and the wheel are not held back anymore, only WM_INPUT and WM_MOUSEMOVE. Also removes the raw mouse registration the game leaves behind when it starts with "Windows Input". With it every report came in twice, which made the sensitivity feel off until you switched the method once. Signed-off-by: OneEarJoe5 <212275319+OneEarJoe5@users.noreply.github.com> * fix(rage-input-five): fix dragging the pause map with "Windows Input" With "Windows Input" you couldn't drag or click on the pause menu map. The capture count reset that runs every frame while the game cursor is visible makes the game drop the held button in that mode. Skip the reset for "Windows Input", the cursor stays centered there anyway. Signed-off-by: OneEarJoe5 <212275319+OneEarJoe5@users.noreply.github.com> --------- Signed-off-by: OneEarJoe5 <212275319+OneEarJoe5@users.noreply.github.com>
Goal of this PR
Fix mouse lag with high polling rate mice. At 1000 Hz the mouse is fine; at 4000/8000 Hz camera
and aim movement lag, and the frame rate drops sharply while the mouse moves.
How is this PR achieving the goal
The game reads raw mouse input one WM_INPUT message at a time with
GetRawInputData, and pumpsmessages until the queue is empty. At 8000 Hz a new report arrives every 125 us. Every pump
iteration (
PeekMessage,DispatchMessage,GetRawInputData,DefWindowProc) takes the windowmanager lock, which other processes reacting to the same mouse contend for. An ETW trace showed
the game's main thread blocking on that lock (
WrResource) ~1400 times per 0.5 s while movingthe mouse, so an iteration takes longer than 125 us. The queue then never runs empty, and the
frame is stuck in the pump.
grcWindowProcedurenow handles raw input in batches:GetRawInputBuffer, whichtakes it off the queue.
Button, wheel, absolute, keyboard and HID input is not merged and keeps its order.
GetRawInputDataanswers those calls from our copy; any other call goes to the real function.
PeekMessageWleaves rawinput and mouse messages that arrive later in the same pump pass for the next frame. Other
messages are still processed right away.
When WM_INPUT is not passed to the game (NUI cursor, console), the pending input is dropped in one
go, as each of those messages would have been dropped anyway.
The game still gets every report: the movement it reads adds up to exactly the raw input, and the
newest report it sees each frame is at most one pump pass old, so 8000 Hz keeps its latency
advantage over 1000 Hz.
This PR applies to the following area(s)
FiveM
Successfully tested on
Game builds: 3258 (FiveM)
Platforms: Windows
Tested in game with an 8000 Hz mouse, moving it hard. Measured with temporary counters, while
moving the mouse:
In both cases the summed movement the game read matched the raw input exactly.
Checklist
Fixes #1082