-
Notifications
You must be signed in to change notification settings - Fork 48
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
Should spec a buffering/refresh interval model of gamepad data? #22
Comments
Let me just explain what I believe to know about the problem without answering your questions. In chromium, as far as I understand, if you process gamepad data in a requestAnimationFrame loop, you will be able to catch any button presses that are clearly distinguishable from jitter. We poll gampads from the OS at 60Hz and we produce a snapshot of the actual state - as provided by the OS, which might already include some buffering and/or delay - which is returned in getGamepads(). The actual timing difference between the poll and the time when requestAnimationFrame fires is arbitrary, but in general if a button was pressed after the last rAF fire and it was hold for at least around 16ms you will see it in the next rAF via getGamepads(). Now as far as I know, the thing about humans pressing buttons is that in practice you always hold it for at least 16ms, thus the theoretical issue with button presses quicker than that is not relevant. Of course all these thinking assumes that our polling is happening at 60Hz no matter what and the same about firing rAF which might always be the case (but we should be close to that for quality gaming experience anyway). With that in mind, I guess my question to you is: do you know any practical examples where lost gamepad events are actually a real problem? Irrespective of whether we miss events in practice, the spec should be explicit about the model - such as whether getGamepad() is returning a live object or a snapshot. In case the snapshot model is chosen, it probably should have some text about the frequency of polling and about exactly how and when can you observe the physical gamepad events. So, the problem is definitely not solved, however I would say that it's important to avoid solving theoretical issues instead of the real ones, so first we should clarify whether the phenomenon of missing events is a real problem with the current spec. |
Thanks for the great comments! I agree that any "superhuman" button presses that only occur for a single digit millisecond duration are of not concern. Not sure whether the OS itself would be registering these either. Although the "all these thinking assumes that our polling is happening at 60Hz no matter what and the same about firing rAF which might always be the case (but we should be close to that for quality gaming experience anyway)." thought could be read a bit in a all bets are off type of scenario for the Gamepad API if one doesn't have 60fps. I think it's rather the hiccup/GC stutter cases and slow frame rates exactly that are the important consideration. We would not want to miss button presses in the event that for example the JS garbage collector decided to take a 500msec pause in a critical moment in a game. I'm leaning to thinking that perhaps Gamepad API should add an event model which ensures best possible promise about no lost events. With this, if the OS buffers up gamepad events, then these could be naturally delivered. And .getGamepads() could always return the most recent data that browser has, which would be good for sampling analog signals when only most recent signal value is of interest. (e.g. racing car throttle position). I would dislike having a snapshot model spec which would go and specify actual millisecond intervals when polling occurs or anything like that. That would feel brittle. On the topic of theoretical vs concrete, and the superhuman question aside, the question of whether the second code snippet above has a danger of losing presses is a concrete issue. This is more rather a question of whether a browser implementation might be using a separate thread to receive gamepad api messages, and the polled data could change mid-flight when JavaScript code is executing. That could make the two code snippets behave differently. Does the spec (intend to) allow that? |
…if subsequent polls might change the data under the hood, which might lead to missing button events if they are buffered. See w3c/gamepad#22. Also reduces the amount of garbage that is generated, and the number of times we jump to a call inside the browser if application iterates through multiple gamepads per frame.
See inline. On Thu, May 5, 2016 at 1:42 PM, juj [email protected] wrote:
It's not clear to me that you really better off processing those events
With the chromium implementation it's definitely not changing on the fly.
|
I think we'd be better off spec'ing events as the solution here, and also spec'ing #8 to clarify when data updates are visible to content. |
Should be covered by #152 ... at least, the proposal should address the above. |
Just for posterity, this is not true anymore, see #46 (comment)
|
Noticed that there has already been quite a bit of discussion of polling vs events model for the Gamepad API. The argument in favor of events over polling has been stated that polling can lose button presses (if they fall in between the polled snapshots) and events can not. I think this is not completely accurate, and being able to lose/miss button presses is somewhat orthogonal issue to events vs polling API.
It would be possible for a browser implementation not to lose any button presses if it accumulates those up internally from OS and buffers them to be returned on the next call to getGamepads(). From the spec viewpoint, it is unclear if this is mandated or prohibited. Even in the absence of browser buffering gamepad button events, there is a question about the granularity of when new live data is allowed to come in.
a) Are conforming implementations of the Gamepad API allowed to miss physical button presses? Or is that considered an implementation bug?
b) Are Gamepad API implementations allowed to buffer up button presses (it gets as events from OS) and return them on the next polled call to navigator.getGamepads() as to not miss any button presses that might otherwise fall in between the polls?
c) Consider the following code:
versus the following code:
In a conforming implementation, are these two functions required to print out the exact same output? Or is it expected that the outputs can differ here? That is, does each call to navigator.getGamepads() (even in subsequent calls in a single function) possibly return new live data? Or is the data provided by the browser allowed to change only e.g. at each turn of requestAnimationFrame() or setTimeout() or setInterval()?
Solving the issue via an event API might be one try, although like it was noted, sending events for analog axes, which often have noise based jitter, might lead to a large constant volume of events being sent. Also games would often need to implement their own state registry buffering of these events in order to check if user pressed button X alone, or Left Trigger + button X, or what the exact value of an analog axis was at the time of a press.
It would be possible to fix the missing button presses trouble in the polling approach by specifying when fresh button state data is allowed to come in, e.g. at each rAF() turn or similar (after exiting any event handler in which getGamepads() was called(?)), which would both allow browsers to buffer up presses for the next poll, and make the above code samples identical.
What are the latest thoughts on this front?
The text was updated successfully, but these errors were encountered: