-
Notifications
You must be signed in to change notification settings - Fork 310
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
FIX: Add workaround for cases where button presses can be missed (ISXB-491) #1935
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to get a summary of the performance impact. The spreadsheet has lots of data but doesn't make it very clear what the overall impact is.
My main concern is that this fixes lost events but we are hiding it behind a flag. I'd like to know the impact of enabling the flag by default.
Packages/com.unity.inputsystem/InputSystem/Controls/InputControlExtensions.cs
Outdated
Show resolved
Hide resolved
Added Paulius to help testing performance on Android |
The original bug project crashes when built on my only Android testing phone (Xiaomi MI 8 Lite) so I used the QA mobile sensor testing project instead when idling and when interacting with the UI buttons. Not sure what to make of the results so I'm just gonna post the screenshot with analyzer data as well as profiler captures. Capture data (In the screenshot blue highlighted area is for simply idling the app and the right green area is me pressing UI buttons every 0.5~ sec) |
These captures don't show any significant slow down so I think this is good to land (pending reacting to feedback above in PR) |
This comment was marked as off-topic.
This comment was marked as off-topic.
Here's one of me just tapping non stop for around 15 secs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see this decoupled from the feature flag as I see this as a critical fix that should always be enabled.
e2b8bed
to
6b544ee
Compare
Have updated to address above comments, plus some extra issues that cropped up. Have added new perf results to the second sheet of the gdoc. |
Packages/com.unity.inputsystem/InputSystem/Controls/ButtonControl.cs
Outdated
Show resolved
Hide resolved
@@ -488,29 +487,47 @@ public void Controls_ValueCachingWorksAcrossEntireDeviceMemoryRange() | |||
InputSystem.actions?.Disable(); | |||
#endif | |||
|
|||
var keyboard = InputSystem.AddDevice<Keyboard>(); | |||
// Value caching is supported for all controls, but with changes to button press detection, ButtonControls will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thanks for updating this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, this makes me wonder, will this evaluation work for detecting "button behavior presses" for controls that are not buttons? E.g. transition of axis under the button behavior (magnitude based) within a sub-frame? Basically this is not unique to buttons in any way, it's all about avoiding aliasing in the sampling process. Not saying these changes not already carry a lot of value, but trying to understand what problems still exist. Hence I wonder if we should setup an additional test case similar to the one done for wasPresseed/wasReleased this frame w.r.t. e.g. axis, or maybe you already can say what we guarantee for that use case? (We could just say, use actions for something like that)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe what you mention will be detected just fine, eg. gamepad has a ButtonControl for "left stick up"?
Packages/com.unity.inputsystem/InputSystem/Controls/ButtonControl.cs
Outdated
Show resolved
Hide resolved
Packages/com.unity.inputsystem/InputSystem/Controls/InputControlExtensions.cs
Outdated
Show resolved
Hide resolved
Packages/com.unity.inputsystem/InputSystem/Devices/InputDeviceBuilder.cs
Outdated
Show resolved
Hide resolved
@@ -3739,7 +3773,8 @@ internal unsafe bool UpdateState(InputDevice device, InputEvent* eventPtr, Input | |||
deviceStateSize); | |||
} | |||
|
|||
if (InputSettings.readValueCachingFeatureEnabled) | |||
// Keyboard has enough ButtonControls that it's faster to find out which have actually changed here. | |||
if (InputSettings.readValueCachingFeatureEnabled || m_Devices[deviceIndex] is Keyboard) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if there is also a synergy with knowing the button count also here? It sounds like the benefit here is actually more related to the number of buttons on the device rather than it being a Keyboard? Hence maybe this should be a threshold based off number of buttons? Its fine as is but something like that would make it more future proof?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated - with some testing with the new changes, it seems that having about 45 buttons that have pressed/releasedThisFrame usage is where it becomes more efficient to take the cache value, so we now swap over at that point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to approve this one now from my perspective and not taking other reviewer comments into account. I left a few questions and minor comments though for consideration. Great to see this being adressed, thanks @graham-huws!
@lyndon-unity Could you help summarise what additional updates are needed to transition this from "Request Changes"? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've going to approve this, but ideally we'd follow up to adjust it to limit the performance impact by only applying the extra checks when there is code that needs it. (I..e I think only if wasPressedThisFrame or wasReleasedThisFrame are used by the user). Ideally we'd defer the work to the call site.
I would like to hear the XR team perspective of the performance impact as there is a risk this is unexceptable in their use case.
Ideally they would have the option to opt out of this performance cost if they don't need if for specific actions/bindings.
Now updated to a new version which only does processing for ButtonControls which have had wasPressedThisFrame/wasReleasedThisFrame called, saving a lot of performance when not many are being utilised. Added V2 benchmarks to the spreadsheet, and new tests which try varying amounts of buttons to test to see the impact. |
… give plenty of info.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the performance is improved for the cases with less calls to wasPressedThisFrame with this update then I'm comfortable with it landing as it fixes the key issue and limits the performance impact to the flows where the checks are needed.
(InputUpdate.s_LatestUpdateType.IsEditorUpdate() ? m_UpdateCountLastReleasedEditor : m_UpdateCountLastReleased); | ||
#else | ||
public bool wasPressedThisFrame => InputUpdate.s_UpdateStepCount == m_UpdateCountLastPressed; | ||
return device.wasUpdatedThisFrame && currentlyPressed && !pressedLastFrame; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is much easier to read than before which is great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if I'm understanding correctly, this old flow can still miss some rapid in frame press/release on the first check, since we haven't run though all the transitions.
Its good we have the more expensive flow opted in, so not always paying the cost if never used, but I'd like to see a comment above to state that this can miss a transition on the first ever call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree on the comment. Then if you care for the first call you may at least call this once up front to get it triggered.
var pressedLastFrame = IsValueConsideredPressed(ReadValueFromPreviousFrame()); | ||
BeginTestingForFramePresses(currentlyPressed, pressedLastFrame); | ||
|
||
return device.wasUpdatedThisFrame && !currentlyPressed && pressedLastFrame; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again this is easier to read which is a good change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, but agree to Lyndons comment.
Did you check consistency with wasPerformedThisFrame? Since that one is only available on actions I think it could have value to have a test that sets up an action bound to button and then coevaluates wasPerformedThisFrame with outcome of wasPressedThisFrame and wasReleasedThisFrame.
(InputUpdate.s_LatestUpdateType.IsEditorUpdate() ? m_UpdateCountLastReleasedEditor : m_UpdateCountLastReleased); | ||
#else | ||
public bool wasPressedThisFrame => InputUpdate.s_UpdateStepCount == m_UpdateCountLastPressed; | ||
return device.wasUpdatedThisFrame && currentlyPressed && !pressedLastFrame; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree on the comment. Then if you care for the first call you may at least call this once up front to get it triggered.
…ests where it times out for being too slow.
262a46f
to
c7e591d
Compare
Description
Fix for ISXB-491.
The current design of the input system package relies on the following method for checking if a button has been pressed on the current frame: Check the current value of the button, and compare to the final value of the previous frame.
The issue with this approach is that presses can be missed if they happened very quickly, or there was some form of lag making the update take longer than intended. Whether a button is pressed is only properly evaluated when asked, so if we don't check every input coming in, some can be missed.
Changes made
This PR seeks to solve this in a very simplistic way - check every value that affects ButtonControls and record their pressed state at the time the change comes in. Current belief is that a "clever" solution to this issue would require a fairly extensive rewrite of how the input system works.
Performance comparison data can be viewed on Sheet 2 here.
Checklist
Before review:
Changed
,Fixed
,Added
sections.([case %number%](https://issuetracker.unity3d.com/issues/...))
.Area_CanDoX
,Area_CanDoX_EvenIfYIsTheCase
,Area_WhenIDoX_AndYHappens_ThisIsTheResult
.During merge:
NEW: ___
.FIX: ___
.DOCS: ___
.CHANGE: ___
.RELEASE: 1.1.0-preview.3
.