libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.54k stars 1.77k forks source link

hidapi_steamdeck: severe input lag if vsync enabled #10149

Closed jorio closed 2 months ago

jorio commented 3 months ago

I maintain (Linux, OpenGL, non-Steam) games that run great on the Steam Deck with SDL 2.28.5.

Upon upgrading to SDL 2.30.4, I noticed severe input lag with the Steam Deck's built-in gamepad (joystick name "Steam Deck", GUID 0300f617de2800000512000000036800).

Each button press takes about half a second to register. This occurs when vsync is enabled in the game; input lag disappears if you turn vsync off.

The input lag also disappears if you get the game to use the second joystick ("Steam Virtual Gamepad", GUID 030079f6de280000ff11000001000000). In SDL 2.28.5, this is the only detected joystick.

The issue can be mitigated with SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, "0"), which reverts to SDL 2.28.5's behavior.

slouken commented 3 months ago

@mmmaisel, can you take a look?

mmmaisel commented 3 months ago

I had a quick look at the source code without doing some real tests and noted the following things:

With this information, I have the following untested theory:

There is some synchronization issue that delays the calls to HIDAPI_DriverSteamDeck_UpdateDevice when synchronizing to the screen which takes about 16 ms at 60 Hz. In the meantime, the HIDAPI fills data in a buffer much faster every 1-4 milliseconds so the next call to the HIDAPI_DriverSteamDeck_UpdateDevice processes some outdated data. Depending on the HIDAPI buffer size, the accumulated outdated data then causes input lag of about half a second.

When the HIDAPI driver is disabled by the SDL_SetHint, a kernel driver is used instead which always present up to date data to userspace when asked without buffering old values.

mmmaisel commented 3 months ago

I can reproduce this issue with the testgamecontroller app on the Steam Deck with Gnome and both Wayland and X11. In my test, I got an input latency of about 1 second.

I also patched the SDL_hidapi_steamdeck driver so it tries to drain the buffer, see this branch. However, this did not fix the issue so I guess there is something else causing the issue outside of the driver.

mmmaisel commented 2 months ago

@jorio, Can you please try if my steamdeck-drain-buffer branch fixes your problem?

In my tests with the testgamecontroller utility, it fixes the latency issue on the Steam Deck.

slouken commented 2 months ago

Oh yes, reading from the controller should definitely be done in a loop, like is done with all the other HIDAPI controllers.

slouken commented 2 months ago

That explains why it's related to framerate, since it's only reading one report every time through the frame loop.

jorio commented 2 months ago

@mmmaisel Sorry - it took me a while to get around to testing this. Can confirm that I can't perceive any more input lag. Thanks a lot!