SDL
SDL copied to clipboard
SDL3: Input freezes when rumbling consistently.
Scenario
Every in-game tick of 20tps I update the controller input using SDL_GetGamepadAxis
and similar.
My game implements rumble. On the same game tick loop, the game checks if the RumbleManager (responsible for creating patterns etc) has a new rumble state for this tick, if it does, it calls
SDL_RumbleGamepad(ptrGamepad, state.strong(), state.weak(), 0)
. If it doesn't, it calls the same, but with a state of [0,0].
Observation
In this game, the rumble manager is called to create a water splash rumble effect when a player lands in water from a height. Flying up to the sky, then starting to fall whilst holding the right stick to the right (causing the camera to constantly look to the right), then immediately letting go of the stick as the rumble begins signifying landing in water, the camera does not stop moving right. I have tracked down this behaviour right to the SDL_GetGamepadAxis
call, where I print the state of the right stick x axis. It is continually printing, showing the driver does not stop polling SDL. This leads me to believe this is the fault of SDL.
Further testing
I implemented a test rumble tone that goes like this:
- scale up the weak tone (over 1 second)
- scale down the weak tone (over 1 second)
- a 1/4 sec strong tone, then immediately a 1/4 sec weak tone, repeated 10 times As previously observed, input stops working as I begin the test tone, however half way through (it's hard to pinpoint exactly where) input begins to work as normal again.
This issue was first observed on macOS 14.2.1 Sonoma, but a user has also experienced this same effect with Windows. Both were using a DualSense controller. As I am currently away, I have no other controllers to test this with. This could then be an issue with the DualSense hidraw driver, but it could also be a wider issue. I will update this thread if I get any test results from other controllers.
This also did not occur on SDL2.
Context
This is the exact code I used to reproduce this https://github.com/isXander/Controlify/blob/1.20.x/dev/src/main/java/dev/isxander/controlify/driver/sdl/SDL3GamepadDriver.java#L177 It's in Java, but the binding is 1:1 with the C library, and it wouldn't make any sense that the binding layer has anything to do with this.
Here's a response I just got back from my user:
looks like it might be an issue specific to sony controllers, just tried a dualshock 4 which has the same problem but also tried a generic xbox controller which did not have the issue. Using ds4windows with the dualsense to emulate an xbox 360 controller works fine
Why are you using 0 for duration? Can you try with non zero value (like 100ms) and check if it still happen?
Why are you using 0 for duration? Can you try with non zero value (like 100ms) and check if it still happen?
I use 0 as it seems to make it an infinite duration, since if the game is lagging and the tick rate is reduced, the rumble wouldn't flicker on and off. Setting it to 0 had caused no issues on SDL2 and I was under the impression it was intended behaviour.
When using 0, SDL will never tell the controller to stop rumble, but the controller will stop rumble by itself after some time (5s for Dualshock). You should use SDL_MAX_RUMBLE_DURATION_MS
to get "infinite" rumble. Anyway it should not cause any issue.
I cannot reproduce this bug in testgamecontroller
with Dualshock4 on Linux. Moving trigger to update rumble, all inputs update correctly. I will leave this to someone else, unless there is more info on how to trigger this.
Even with a 5 second duration it still happens.
any update on this?
Not from me. Just waiting on SDL team.
I did some further testing:
I can now also repeat this on macOS Sonoma with a Stadia Controller connected via USB. I believe this can now rule out the DualSense controller firmware as a cause of this issue.
I have created some test vibration patterns with a duration of 2 seconds (40 ticks)
- 100% strong, 0% weak - input freezes for the duration of 2 seconds
- 0% strong, 100% weak - input freezes for the duration of 2 seconds
- 100% strong, 100% weak - input freezes for the duration of 2 seconds
- 50% strong, 0% weak - input does not freeze whatsoever
- 50% strong, 50% weak - input does not freeze whatsoever
I do have a theory to what is causing this:
I recently implemented the DS5 effect state to toggle on/off mute light. My game loop runs at 20 ticks per second; when calling SDL_SendGamepadEffect
once every tick, the controller appears laggy, frozen. When only calling it when the mute light changes, it's fine.
My rumble manager supports dynamic effects which polls a new state from an effect instance every tick, and calls SDL_RumbleGamepad
accordingly, even if the strong and weak values are identical (this is so the duration does not run out). My theory is that calling rumble so frequently is somehow lagging SDL. What I do not understand however is why a weaker effect does not trigger this, since the same amount of data is being sent.
Note that the main thread of the game does not freeze, so I have to assume SDL has its own threads?
@isXander, it looked like you created a test program to reproduce the issue and then deleted it? A test program would be really helpful here to reproduce the problem.
@isXander, it looked like you created a test program to reproduce the issue and then deleted it? A test program would be really helpful here to reproduce the problem.
The test program I made had a bug in it that displayed a similar issue. Once I fixed it, I couldn't repeat it. So I deleted it since I couldn't replicate the issue.
I'm currently exploring potential solutions that might be (yet another) JNA issue. Will keep this thread updated with any more stuff that I find.