Repository navigation
feat(lift): app rig drives lift viewpoints + metric depth aux output - #1868
Merged
Merged
Conversation
Collaborator
Author
|
The three |
… auxiliary metric depth API (XR_DXR_lift spec v2 -> 3, ADR-048 Addendum A): - An XrDisplayRigDXR / XrCameraRigDXR (XR_DXR_view_rig) chained on XrLiftOptionsDXR or XrWeaveRectLiftDXR drives the TRACKED lift viewpoints with the xrLocateViews rig math (the lifted rect is the screen). - EXPLICIT viewpoints are accepted on lifted weave rects. - XrLiftDepthRequestDXR (283) on XrLiftStreamCreateInfoDXR asks an SBS / NVIEW stream for its depth map as an auxiliary output; XrLiftDepthResultDXR (284) on XrLiftResultDXR returns it (texture + fence on first acquire / realloc, format, units, encoding, intrinsics, convergence depth, the viewpoint it refers to and a column-major depthToDisplay transform that puts the convergence depth on the screen plane); XrLiftDepthPropertiesDXR (285) on XrLiftPropertiesDXR reports the capability. DP contract (append-only, ADR-020, no ABI bump): - xrt_dp_lift_params += viewpoint_source, nominal_z_m (XRT_DP_LIFT_HAS_APP_RIG). - xrt_dp_lift_caps += aux_outputs, aux_depth_semantics; xrt_dp_lift_stream_info += aux_outputs, aux_depth_format; new struct xrt_dp_lift_depth (XRT_DP_LIFT_HAS_AUX_DEPTH). - D3D11 DP vtable slot 33: lift_get_depth (XRT_DP_D3D11_HAS_LIFT_DEPTH), called right after a successful lift_convert of a stream that asked for depth; helper xrt_display_processor_d3d11_lift_get_depth. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n the lift thread R5 (#1860): an XrDisplayRigDXR / XrCameraRigDXR on a lift is mapped with the shared displayxr-common rig core xrLocateViews runs (u_lift_rig.{h,c}; aux_util now links displayxr::math_core). Display rig = dxr_display3d_compute_views eye_display with the rect as the screen (m2v 1); camera rig = the physical viewer whose Kooima frustum onto the rect equals the camera frustum (E = Z0 (l invd + z), Z0 = rect_h / 2 tan(vfov/2)). The rig replaces the policy's ipd / parallax; axis mask, ease-back and clamp still run on the viewer first. It rides with the options (cleared by options without a rig), on submits and on lifted weave rects. EXPLICIT viewpoints are accepted on lifted weave rects (staged per rect by a new lift_weave_rect_viewpoints IPC call: 8 rects of them do not fit IPC_BUF_SIZE). The DP is told viewpoint_source + nominal_z_m; the echo reports the rig eyes. R6 (#1861): SBS / NVIEW streams created with XrLiftDepthRequestDXR call the new DP slot lift_get_depth right after each successful lift_convert; the depth is copied into the same out ring slot (second keyed-mutex texture), then into a per-stream depth export texture under the views' fence (one fence value covers both). The runtime derives the intrinsics (METRIC only) and depthToDisplay (u_lift_depth.{h,c}: X = R + C + (P - C) d / dc, one column-major 4x4) from the viewpoints and rect it already owns; RELATIVE depth reports neither. New IPC call lift_get_depth_output; lift_stream_create carries aux_outputs / aux_depth_format; ipc_lift_result carries xrt_lift_depth_info. sim_display's fake lift returns a synthetic metric ramp (1..2 m) so the path runs without hardware (SIM_DISPLAY_FAKE_LIFT=1). Tests: tests_aux_lift_rig_depth — display rig == located eye_display / m2v after window rebase (and the same frusta), camera rig frusta == the camera3d core's, infinite convergence collapses the views, convergence depth lands on the rect, d -> 0 at the viewpoint, rays stay collinear, invalid inputs, decode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…play math) + ADR-048 Addendum A - XR_DXR_lift.md: header table -> v3, §4.2 app rig (rig -> viewpoint mapping and the camera-rig frustum-equivalence proof), §4.3 auxiliary depth (request, result, decode, intrinsics, the depthToDisplay derivation + matrix table, DP side), §6 EXPLICIT on weave rects, §10 / §11 / §14 rows. - ADR-048 Addendum A: A1 the app rig is computed with the xrLocateViews core, A2 depth is an auxiliary same-inference output with a runtime-derived display transform; why a new slot instead of an out-struct on lift_convert. - xrt_plugin_iface.md lift section: appended params / caps / stream-info fields, struct xrt_dp_lift_depth, slot 33 lift_get_depth. - extensions index.json note. gen_adr_index --check, gen_extensions_index --check and check_doc_paths pass (ADR titles unchanged). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfattal
force-pushed
the
feat/lift-app-rig-and-depth
branch
from
October 8, 2026 22:40
ea2a60c to
a46d671
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #1858, closes #1860, closes #1861.
Stacked on #1864 (base
feat/lift-viewpoint-policy, rebased onto its amended headedf61ecdf). This covers runtime items R5 and R6 (phases 2 and 3) of the lift camera design:XR_DXR_lift goes to spec v3. It is a separate version, not folded into v2, because v2 (#1864) can ship on its own. Apps key these features on
SPEC_VERSION >= 3.Commits
a5af88f5d: API + DP contract. Pushed early so the vendor plug-in can build P2 against it.API (XR_DXR_lift.h)
XrDisplayRigDXRorXrCameraRigDXR(fromXR_DXR_view_rig) can be chained onXrLiftOptionsDXR, or directly onXrWeaveRectLiftDXR.xrLocateViewsruns, using the lifted rect as the screen. No math is duplicated.XrLiftDepthRequestDXR(283), chained onXrLiftStreamCreateInfoDXR.XR_ERROR_VALIDATION_FAILURE.preferredFormatis a DXGI format hint.XrLiftDepthResultDXR(284), chained onXrLiftResultDXR. It carries:depthValid.depthTextureandfence, which follow the views' export rule: handed out on the first acquire that carries depth, then on each reallocation. It is the same fence object as the views', with the samefenceValue.extent,format,units,encodingwithvalueScale/valueOffset, andnearDepth/farDepth.sameInferenceandframeId.focalLengthPxandprincipalPointPx.convergenceDepthandviewpoint.depthToDisplay, a column-major 4×4 matrix.XrLiftDepthPropertiesDXR(285), chained onXrLiftPropertiesDXR:auxDepthSupportedandauxDepthSemantics.DP contract
All changes are append-only (ADR-020). There is no ABI bump.
xrt_dp_lift_paramsgainsviewpoint_source(TRACKED / EXPLICIT / DISPLAY_RIG / CAMERA_RIG) andnominal_z_m. Feature macro:XRT_DP_LIFT_HAS_APP_RIG.xrt_dp_lift_capsgainsaux_outputsandaux_depth_semantics.xrt_dp_lift_stream_infogainsaux_outputsandaux_depth_format.struct xrt_dp_lift_depth(feature macroXRT_DP_LIFT_HAS_AUX_DEPTH). It carries:convergence_depth,same_inferenceandvendor_frame_id.lift_get_depth(XRT_DP_D3D11_HAS_LIFT_DEPTH).lift_convertof a stream that asked for depth.lift_convertbecause that signature has shipped and is frozen. With a separate slot, an older plug-in simply has no slot, which reads as "no depth".The math
dxr_display3d_compute_views(...).eye_display, with the rect as the screen and m2v = 1. This equals the locatedeye_display / m2v.E = Z0·(l·invd + ẑ), withZ0 = rect_h / (2·tan(vfov/2)).convergenceDiopters0 (convergence at infinity), all views collapse into one, so the lifted content has no parallax.xrLocateViews, chainXrLiftViewControlDXRwith XYZ and recentering OFF.depthToDisplay(spec §4.3):X = R + C + (P(un,vn) − C)·d/dc, whereCis the viewpoint midpoint andPis the texel's position on the rect.d → 0, it lands at the viewpoint.(un·d, vn·d, d, 1), so it is a single matrix.Implementation notes
u_lift_rig.{h,c}maps the rig; aux_util now linksdisplayxr::math_core.u_lift_depth.{h,c}builds the depth transform.lift_get_depth_outputcall.lift_stream_createcarries the aux request, andipc_lift_resultcarriesxrt_lift_depth_info.IPC_BUF_SIZE(1024). So each rect's viewpoints are staged with a newlift_weave_rect_viewpointscall just beforelift_weave_rects.lift_get_depthwithSIM_DISPLAY_FAKE_LIFT=1, so the whole path can run without hardware.Logging
[lift] stream N app display rig: ipd=… parallax=… perspective=…,… app camera rig: …, and… app rig cleared.[lift] stream N auxiliary depth: WxH fmt=F units=metric|relative encoding=… same_inference=… convergence=… intrinsics=yes|no transform=yes|no[lift] stream N depth export texture WxH fmt=F ready[lift] stream N asked for auxiliary depth but the module returned none[ (the plug-in has no lift_get_depth slot)]aux=.Verified on the build box
scripts\build_windows.bat generate+buildin the worktree is clean, with no new warnings.ctest -C Release -R liftpasses:tests_lift_mailbox,tests_aux_lift_viewpoint, and the newtests_aux_lift_rig_depth(120 assertions). The new test checks:eye_display / m2vafter window rebase, with the same frusta.d → 0lands at the viewpoint.tests_oxr_view_space_mode_floor,_mode_pinnedand_mode_floor_off.first_unfillable_modeagainst this box's registered display plug-in._package\bin\displayxr-cli.exe selftestPASSED, includinglift_capsagainst the installed released vendor plug-in. So older plug-in struct sizes still work with the new contract.gen_adr_index.py --check,gen_extensions_index.py --checkandcheck_doc_paths.pyall pass.Owed hardware tests
These need the service restarted with this build. Test 3 also needs the vendor plug-in built against this contract (P2).
SIM_DISPLAY_FAKE_LIFT=1and the sim plug-in. Create an SBS stream withXrLiftDepthRequestDXR, submit frames, and acquire withXrLiftDepthResultDXRchained.depthValidtrue, R32F at input size, METRIC / LINEAR,valueOffset1, intrinsics valid,transformValidtrue, and the samefenceValueas the views.[lift] stream N auxiliary depth: WxH fmt=41 units=metric … transform=yes.depthToDisplayatd = convergenceDepth(1.5 m with AUTO) should land on the rect.XrDisplayRigDXRon a weave-rect lift, for example ipd 0.5 and perspective 1.5.[lift] stream N app display rig: ipd=0.50 … perspective=1.50.XrLiftResultViewpointsDXRecho should equal the app'sxrLocateViewseye_display / m2v(chain XYZ + OFF to get an exact match).XrCameraRigDXRand changeconvergenceDiopterslive. The lifted parallax should change in step with the app's own 3D (eyeball on the panel with a mixed 3D + lifted-video app).XrLiftDepthPropertiesDXRshould report supported + METRIC. On a synthetic scene of known depth, the convergence plane should land at z = 0.VALIDATION_FAILURE. The INFO line[lift] stream N viewpoints: … axis=3should show the rebased explicit eyes.🤖 Generated with Claude Code