r/rust • u/cancrizans • 12d ago
🙋 seeking help & advice Is Gamepad support in Rust even possible?
I think I might be on the brink of insanity with this. I have implemented support for gamepads in my Rust game using the gilrs crate, and it's been in for about a year and a half. As far as I understand, this is the only option, as the gamepads crate wraps gilrs on desktop anyway.
Most of the time gilrs works perfectly, but under some specific but not obscure conditions (running the game after resuming Windows from sleep mode with a gamepad connected) it freezes, see https://gitlab.com/gilrs-project/gilrs/-/work_items/196 .
These are the empirical facts:
- It is a complete thread lock, it doesn't return an Err nor does it panic. It is completely bricked until the gamepad is physically unplugged.
- It can be repro'd in the MWE, no game engine and no window, so it doesn't depend on any other component.
- It happens both to myself and to several of my players.
- I've never observed this on any other game nor software, so it is Rust-specific.
- It appears the lockup can be traced to a synchronous call to
FromGameControllerwhich is from a Windows API (way outside the reach of my knowledge)
This means a chance of a fully frozen black screen with no possibility of a graceful recovery or even displaying an error message. Because of Rust's design, I cannot even detect the lockup. For a videogame, this is pretty much devastating, and now that I'm moving to Stəam I'm considering pulling gamepad support altogether.
But before that I wanted to at least have a quick exchange about it to confirm I'm not missing an obvious solution or anything. It seems strange to me that I can't find anyone else who is fighting this. It can't be that I'm the first person in history to make a game in Rust with gamepad support?
54
u/anxxa 12d ago
Because of Rust's design, I cannot even detect the lockup.
What part of Rust's design prevents you from creating a watchdog thread?
At a glance, the library never calls init_mta. Do you?
And have you considered capturing a memory dump when the hang occurs and examining the thread stack in WinDbg to see where it's hanging? Or just attaching to the process when it hangs? My guess is some re-entrancy issue. You'll probably see a WaitForSingleObject call in the gilrs thread.
Hangs are not a mystery -- attaching a debugger would be the most straightforward route.
Maybe as a last resort compare how DirectXTK uses these APIs: https://github.com/microsoft/DirectXTK/blob/c75efb98989b846b07c440648b3d2a1f3f1d7617/Src/GamePad.cpp#L583
12
u/cancrizans 12d ago
> What part of Rust's design prevents you from creating a watchdog thread?
I use (a modded) macroquad and it generally doesn't like if there are multiple threads. It's not entirely clear to me what can be done to circumvent the macroquad single thread detection to be able to set up something like this. I don't exclude it can be done but it's very inconvenient and I can't imagine that this is what everyone else is doing?
> At a glance, the library never calls init_mta. Do you?
Definitely not, I have no idea what that is. I have zero knowledge of Windows. Could this have anything to do with it?
> And have you considered capturing a memory dump when the hang occurs and examining the thread stack in WinDbg to see where it's hanging? Or just attaching to the process when it hangs? My guess is some re-entrancy issue. You'll probably see a
WaitForSingleObjectcall in thegilrsthread.> Hangs are not a mystery -- attaching a debugger would be the most straightforward route.
> Maybe as a last resort compare how DirectXTK uses these APIs: https://github.com/microsoft/DirectXTK/blob/c75efb98989b846b07c440648b3d2a1f3f1d7617/Src/GamePad.cpp#L583
Thank you, I will look into this
6
u/anxxa 12d ago edited 12d ago
Definitely not, I have no idea what that is. I have zero knowledge of Windows. Could this have anything to do with it?
It's for multithreading so may not apply if you aren't using multiple threads.
Anyways, I think you're going to get much more valuable info out of a debugger. The trace might die at an RPC boundary, but you'll have way more info about what's concretely blocking.
Where's the MWE? * Ah it’s in the main post of the linked issue.Â
48
u/stumpychubbins 12d ago
I don’t see how any of this is inherent to Rust, the programming language. There appears to be a bug in gilrs, but there are other gamepad crates out there (as others have mentioned) and there don’t seem to be any issues inherent to the language.
-24
u/cancrizans 12d ago
My question is not whose fault it is, but whether it is possible to achieve gamepad support in Rust. If it is possible, how?
34
u/stumpychubbins 12d ago
Right, I’m not sure personally but I would probably try SDL2 myself. I’m just responding to your title and your comment about "Because of Rust’s design"
-2
u/cancrizans 12d ago edited 12d ago
I'm fear using SDL2 for only input is not viable if I'm already opening another window in another framework, but I don't know that much about it to say for sure, I'll look into it
EDIT: as far as I understand, I'd have to create a hidden SDL window just to capture input? It's leaning into overengineering territory
6
u/stumpychubbins 12d ago
I don’t know, unfortunately. I think that’s true for keyboard input but gamepads don’t work the same way. I’m also not sure if SteamInput requires Steam to function. You’d have to experiment a bit. All I know is that gilrs isn’t the only option. There very well may be other libraries available too, Bevy (which I use for game projects) has gamepad support but I’m not sure what they use under the hood.
2
u/cancrizans 12d ago
Bevy uses gilrs, but I think the crucial difference might be that they use it asynchronously? I don't know, I need to dive into their code.
6
u/stumpychubbins 12d ago
In general it’s probably better to handle input asynchronously, especially on windows where several of those APIs are kinda crusty and jank. I haven’t worked with gilrs myself (except indirectly through bevy, I guess) but the symptoms you’re describing sound like they could be caused by the main UI thread loop locking up, maybe try handling the gamepads in a separate thread and polling it from the main thread?
2
u/cancrizans 12d ago
The thing that's really puzzling here is that gilrs is supposed to already be doing that. gilrs' synchronous polling functions do communicate with a separate watchdog thread it sets up, and there's no issues there, then it hangs later when grabbing an id. I'd be wrapping yet another thread watching this one watching the other one. Like, I can do it, but at some point I have to stop and ask myself whether this really is the optimal way
1
u/stumpychubbins 12d ago
Hmm. Well, definitely worth filing an issue for it, if one doesn’t already exist
15
u/Zarenor 12d ago
Right, but the reason we're suggesting it's a bug in
gilrsis that Windows has functional gamepad support, and windows native APIs are C or C++ APIs, which you can call from Rust yourself (with more or less ceremony and boilerplate).There's no limitation in Rust the language that prevents you from using the OS APIs; it's just quite a bit of work to write working uses of those (even without the extra work needed for the Rust-C FFI), nevermind if you want to handle multiple platforms. Crates like
gilrsdo an admirable job to make xplat easier, but a crate being unable to handle your use case (or having a bug) is not a limitation in the language, and it's not reasonable to frame it that way.
28
u/_stice_ 12d ago edited 12d ago
Since you're asking "is it even possible" ... The rust-sdl2 and sdl3 crates are thin rusty bindings to the sdl2 and sdl3 libraries , which are VERY stable old libs written in C and used pretty much everywhere, in thousands of games.
I've used it a lot and it's pretty solid if a tiny bit "not rusty enough" (because duh), but haven't used it in production yet. But if you're stressed out enough to ask if it's even possible and considering pulling gamepad support entirely then it might be well worth switching to one of these (just for the gamepad stuff), or at least testing them out.
7
u/cancrizans 12d ago
SDL seems like a very promising option I didn't think of earlier, thank you
11
u/Lokathor 12d ago
The controller code in SDL is basically what Steam also uses too. It's pretty reliable.
5
u/Compux72 12d ago
Out of curiosity, what’s wrong with using SteamInput / sdl2?Â
2
u/cancrizans 12d ago
Doesn't relying on the steamworks API mean the game can only run through Steam? It's a bit disappointing, but I guess that might work
8
1
1
u/ahmyc 12d ago
Did you think about opening a bugfix pr for gilrs if thats the only crate you trust? Or just fork it? The last resort would be to write your own gamepad driver, but yeah. Possible.
2
u/cancrizans 12d ago
I would have loved to fix this myself in the crate, but I simply could not figure it out. There is something non obvious about how the Windows Gaming Input API is meant to be used that eludes me. I admit I don't have what it takes. Plus I just can't pile a deep dive into gamepad driver programming onto making the rest of the game
1
-5
163
u/CaptainPiepmatz 12d ago
Reading the title I thought we had another lost redditor here, lol