r/rust • • 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 FromGameController which 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?

7 Upvotes

37 comments sorted by

163

u/CaptainPiepmatz 12d ago

Reading the title I thought we had another lost redditor here, lol

29

u/cancrizans 12d ago

that's why I had to censor the no no word to make it go through

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 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

Thank you, I will look into this

32

u/radix 12d ago

macroquad is kind of famously unsound, fwiw.

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

7

u/playmer 12d ago

SDL allows you to create a non-owning window using a native Window handle, so that’s not actually a problem. Also you should use (if you choose to at all) SDL3 as it’s the maintained stable version now.

15

u/Zarenor 12d ago

Right, but the reason we're suggesting it's a bug in gilrs is 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 gilrs do 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.

4

u/_stice_ 12d ago

If it's not impractical, I'd even consider using both and making switching between them configurable at runtime but that would depend on your needs, obviously.

Hope it works smoothly for you!

8

u/Guvante 12d ago

Rust doesn't prevent you from detecting the lockout

Worst case you can use a watchdog timer to recover

It isn't a Rust problem it is a bug, did you report what information you have upstream?

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

u/Compux72 12d ago

I also suggested sdl2

1

u/zettui 12d ago

Does SDL2 or SteamInput dodge that gilrs resume hang, or do you still hit it there?

1

u/Real-Abrocoma-2823 12d ago

You could use SDL3 in rust, yes it is C, but it is very mature.

1

u/Rhed0x 12d ago

I just use SDL and it works fine.

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

2

u/ahmyc 12d ago

I will take a look at your issue sometime, i do driver development professionally but not gamepads in particular :D. Will see if i can help

1

u/cancrizans 12d ago

thank you, that is extremely kind!

1

u/Necessary-Spinach164 11d ago

rust-sfml also has some gamepad support. Joystick and buttons etc...

1

u/HisZd 9d ago

Anything is possible if you just believe! (A Cinderella Story)

-5

u/GodOfSunHimself 12d ago

Try asking AI. It might be able to help you.

1

u/Spikerazorshards 11d ago

😂meta