Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arbitrary buffering of API calls is causing issues #46

Open
tkodw opened this issue Nov 2, 2016 · 7 comments
Open

Arbitrary buffering of API calls is causing issues #46

tkodw opened this issue Nov 2, 2016 · 7 comments

Comments

@tkodw
Copy link

tkodw commented Nov 2, 2016

In many current implementations of the Gamepad API calls to getGamepads does not make API calls to the OS to get updated gamepad state and instead return stale data.

Chrome has an arbitrarily chosen polling rate of 16 ms that applies to all platforms.
https://cs.chromium.org/chromium/src/components/exo/gamepad.cc?sq=package:chromium&dr=C&rcl=1478013686&l=36

Firefox has an arbitrarily chosen polling rate of 50 ms (!!!) for windows.
https://searchfox.org/mozilla-central/source/dom/gamepad/windows/WindowsGamepad.cpp#52

A very common OS + Gamepad configuration is probably Windows with an Xbox One or Xbox 360 controller. Both of those controllers have drivers that poll internally at 8 ms intervals by default.

In Chrome's case, since the internal polling rate is half of the gamepad polling rate, half of the updates from the controller will be lost.

With this configuration, buffering API calls adds additional latency of up to 24 ms on Chrome and up to 58 ms on Firefox.

You can test this yourself with a joy to key program. With a joy to key conversion program that polls for button presses at a 6 ms interval and converts them to keypresses, I've observed a keypress being detected by the browser 54 ms before the triggering button press in Firefox.

The additional latency is high enough that the Gamepad API typically provides a much worse experience for games compared to a keyboard or joy to key mapping program.

Can something be done to discourage providing very stale gamepad state when calling getGamepads?

@sgraham
Copy link
Contributor

sgraham commented Nov 2, 2016

I sympathize with the problem, but I'm not sure what we should do, given the historical APIs this code has to call.

In Chrome at least, it is unlikely that code would be accepted that requires increasing the timer frequency above the default 16ms due to concerns about battery.

Is the 8ms polling interval for the Xbox controllers documented somewhere? That might make a more compelling case.

@luser
Copy link
Contributor

luser commented Nov 3, 2016

I'm not really sure how we solve this with XInput, to be honest, since it doesn't provide a notification API. I don't think any browser is going to make getGamepads() call directly into XInput, since it's likely to be executing in a sandboxed content process. For other sources of input we generally get notified on new data, so adding events to the spec would fix this use case.

@tkodw
Copy link
Author

tkodw commented Nov 4, 2016

Is the 8ms polling interval for the Xbox controllers documented somewhere? That might make a more compelling case.

I can't find any official documentation for it. I've observed an 8 ms refresh rate when testing both Xbox 360 and Xbox One controllers with the default USB drivers on Windows 10 and Ubuntu. Microsoft may change it by updating the driver in the future. The default polling rate for most USB input devices seems to be 8ms since it works with older USB hardware revisions.

I'm not really sure how we solve this with XInput, to be honest, since it doesn't provide a notification API.

I agree that there is no optimal solution with XInput. Applications using XInput must poll the API at an even higher rate than the driver poll rate to get accurate timing. The only power-friendly solution I can think of is to adaptively increase the XInput polling rate when the Gamepad API is frequently called.

In Chrome at least, it is unlikely that code would be accepted that requires increasing the timer frequency above the default 16ms due to concerns about battery.

Those timers shouldn't be firing at a high rate unless you have a gamepad connected and pressed a button on it. Seems like a low risk for mobile devices.

@sagoston
Copy link
Contributor

@luser Adding an events API would still not remove the latency when the browser's polling rate is the problem. It could alleviate the client's poll rate but we're still stuck with the browser's latency

@tkodw I don't know what we can add to the spec to discourage a browser from introducing latency.

Any suggestions?

@mrmcpowned
Copy link

The only power-friendly solution I can think of is to adaptively increase the XInput polling rate when the Gamepad API is frequently called.

Isn't the browser privy to the device's charge state? It'd make sense to simply enable a high poll if the device is charging, which would be a likely scenario where the high rate would be justified while having no impact on battery. Desktop devices would always poll at the fastest rate and devices with batteries would poll at the fastest rate when connected to power.

@marcoscaceres
Copy link
Member

marcoscaceres commented Aug 12, 2021

Updated link above for Firefox:
https://searchfox.org/mozilla-central/source/dom/gamepad/windows/WindowsGamepad.cpp#52

const uint32_t kWindowsGamepadPollInterval = 50;

@nondebug
Copy link
Collaborator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants