FIX: [XRA-675] PoseControl isTracked returns false via non-optimized read paths#2443
FIX: [XRA-675] PoseControl isTracked returns false via non-optimized read paths#2443kevin-zakszewski wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
💡 Harness Review
The fix is focused, but the new Pose fast-path gate now accepts isTracked configurations that the old check deliberately excluded, which can make the parent control bypass child-control semantics in overridden layouts.
Reviewed commit 1fdc5db4
🤖 Helpful? 👍/👎
There was a problem hiding this comment.
This weakens the safety check for the kFormatPose fast path. Before this change, isTracked.optimizedControlDataType == InputStateBlock.kFormatByte only succeeded when AxisControl had no extra processing and the state was byte-aligned; now we only check the raw state block shape. That means an overridden Pose layout can set isTracked parameters such as invert, normalize, scale, clamp, or even a non-zero bitOffset, and PoseControl will still return kFormatPose. In that case PoseControl.ReadValue() / WriteValueIntoState() will raw-copy PoseState and bypass the child ButtonControl semantics, so poseControl.ReadValue().isTracked can disagree with poseControl.isTracked.ReadValue(). Please reintroduce the old semantic guard explicitly here (at least bitOffset == 0 and no AxisControl preprocessing on isTracked) before enabling the struct fast path.
🤖 Helpful? 👍/👎

Description
XRA-675
Fix
PoseControl.isTrackedalways returning false via non-optimized read pathsPoseState.isTrackedwas declared withsizeInBits = 8to enable thekFormatPoseoptimization. However, this caused InputStateBlock.ReadFloat() to treat the bool byte value as an 8-bit normalized quantity(1/255 ≈ 0.004)instead of a discrete 0.0 or 1.0. Since0.004falls below the0.5button press threshold,isTrackedalways returned false when read through non-optimized code paths, including the Input Debugger.Summary of Changes
PoseControl.cs — two changes:
sizeInBits = 8tosizeInBits = 1. This makesInputStateBlock.ReadFloat()use theReadSingleBitpath, which correctly returns0.0for1.0f. The struct layout is unaffected -StructLayout(LayoutKind.Explicit)withFieldOffsetattributes controls the memory layout independently ofsizeInBits.isTrackedvalidation fromisTracked.optimizedControlDataType == InputStateBlock.kFormatByteto checkingisTracked.m_StateBlock.format == InputStateBlock.kFormatBit && isTracked.m_StateBlock.sizeInBits == 1. This preserves thekFormatPosefast path (direct*(PoseState*)ptrstruct cast), which remains valid because the C# bool at byte 0 is always stored as a full byte (0 or 1) regardless of the declared bit width.Testing status & QA
Added the test
Controls_PoseControl_IsTracked_ReadsCorrectly- parameterized with[TestCase(true)]and[TestCase(false)]to run with optimized controls both enabled and disabled. For each case it:poseControl.isTracked.isPressedreturns trueposeControl.isTracked.ReadValue()returns 1.0fposeControl.ReadValue().isTrackedreturns trueisTracked = 0and verifies all three return false/0.0fOverall Product Risks
Comments to reviewers
With this fix,
isTrackedloses its AxisControl-level optimization — it previously gotkFormatByte (via sizeInBits = 8), and now falls through tostateBlock.ReadFloat()sinceAxisControlhas no fast path for 1-bit controls. The performance difference should be negligible (both end up reading a single bit), and thekFormatPosebulk optimization is preserved, but it's still a gap.I looked into adding a
kFormatBitoptimization toAxisControlso that 1-bitButtonControlsget a directReadSingleBitfast path. This would restore the optimization for isTracked, put thePoseControlcheck back on the standardoptimizedControlDataTypepipeline, and benefit other 1-bit button in the system (mouse, keyboard, gamepad, etc.). We wanted to bring this up and see if this is worth following up with. The main concern is the wider blast radius — it touchesAxisControl, which affects every device type, so it would need a proper audit and test pass.Checklist
Before review:
Changed,Fixed,Addedsections.Area_CanDoX,Area_CanDoX_EvenIfYIsTheCase,Area_WhenIDoX_AndYHappens_ThisIsTheResult.During merge:
NEW: ___.FIX: ___.DOCS: ___.CHANGE: ___.RELEASE: 1.1.0-preview.3.