Repository navigation
feat(weave): multi-screen M6 for present-owners — weave rects per screen, per-screen eyes out (XR_DXR_weave v19) - #1913
Merged
Conversation
…ve v19) A present-owner's bound window that straddles two 3D screens is now woven per screen by comp_d3d11_service_weave_submit, each screen's part by that screen's display processor, and the caller gets one eye set per screen plus every weave rect cut at the seams (#1884, ADR-047 Amendment 4). Service: batch (v3) and v6 submits from a client that sent compositor_segments_enable run the bound window through a segment manager of the present-owner's own (comp_d3d11_segments on sys->device, where the handback and the #1172 ingest DP live): comp_segments_compute over the client area, the session's weave DP on the primary screen, windowless per-screen DPs elsewhere (scissor = the segment, present origin), flat 2D where nothing can weave, the v4 overlay composited by the post-weave blit. Single-screen windows, legacy single-rect submits and clients that never opted in take the existing path unchanged. The drag snap asks the majority screen's segment DP (comp_d3d11_segments_snap_dp, Amendment 2's hysteresis) and falls back to the panel DP. Extension: XR_DXR_weave spec 19 adds XrWeaveOutputRectPartsDXR (chained on XrWeaveOutputDXR) with XrWeaveScreenSegmentDXR / XrWeaveRectPartDXR; type 1004999292. IPC: weave_get_segments appended to proto.json (the xrt_segment_metrics table with each screen's eyes), fetched only when the caller chains the struct; the client cuts its rects with u_weave_rect_parts. Tests: tests_weave_segments (straddling / single-screen / off-primary / negative-desktop / cap cases, and the weave_get_segments reply round trip), tests_ipc_proto pins the append. Part of #1884 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
weave_rpc_probe_d3d11_win chains XrWeaveOutputRectPartsDXR when the runtime reports XR_DXR_weave spec >= 19 and logs the per-screen table and the weave rect's parts on every geometry change, so a two-panel rig can watch a window dragged across the seam go from one display processor to two and back. Part of #1884 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ract Present-owner weave rects are segmented per screen with per-screen eyes out: ADR-047 Amendment 4, comp-segments.md "Present-owners on the weave service", XR_DXR_weave.md section 5g + version history + consumers, the index.json summary, and the multi-screen roadmap's M6 row. Part of #1884 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
|
Rig (2026-10-10, two panels, dev service from this branch, dev Leia plug-in): the forced-IPC present-owner probe with |
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 #1884
What
The runtime half of multi-screen M6 for the browser. A present-owner (
XR_DXR_weave) whose bound window straddles two 3D screens is now woven per screen bycomp_d3d11_service_weave_submit, and the caller gets one eye set per screen plus every weave rect cut at the seam.comp_d3d11_service.cpp): batch (v3) and N-view (v6) submits run the bound window's client area throughcomp_segments_compute(canvas = the whole window). The session's weave DP weaves the primary screen's segment. Each other screen's windowless DP (create_dp_d3d11_for_screen,set_present_origin, viewport + scissor = the segment) weaves its own, all into the same woven handback. Where nothing can weave, the segment is flat 2D. The v4 overlay is composited after that by the runtime's post-weave blit, because no segment DP covers the whole window. This reusescomp_d3d11_segmentsfrom feat(multi-screen): segments + per-segment views on the service / IPC path (stacked on #1878) #1881. The present-owner gets a manager of its own (weave_segs), made onsys->device, which is where the handback and the Service crash-loops serving a browser (present-owner) client on v2.8.0-112 — access violation in igd10iumd64 via SimulatedRealityDirectX during weave #1172 ingest DP live. It is built from the same opt-in screen list (compositor_segments_enable) and released with the compositor.weave_seg_updatereturns false before anything else for these.xrWeaveSnapWindowRectDXRaskscomp_d3d11_segments_snap_dp. That picks the DP of the screen holding the majority of the window at the proposed position, usingcomp_segments_owner_*with Amendment 2's 20 % / 0.5 s hysteresis. It is a separate owner from the window-handle one, because nothing is rebuilt. If that screen has no DP yet or its DP cannot snap, the call falls back to the panel DP.client_presentsfield was appended tocomp_d3d11_segments_frame(zero-init = old behaviour) so segment DPs are told what the session DP is told, plus the snap-owner query.weave_get_segmentsis appended toproto.json. It returns the last submit'sxrt_segment_metrics(the per-segment-views table) with each screen's eyes. The primary's eyes are the submit's own base eyes; the others are predicted from their segment DPs.weave_submit's reply is unchanged.oxr_weave.c): when the caller chains the new struct, the state tracker fetches the table and cuts the submitted rects at the seams withu_weave_rect_parts(new, header-only,auxiliary/util/). The rects cross the wire once.Why
The browser is a present-owner, so it never reaches the in-process sites or the direct-pipeline segment path from #1881. Its inline-3D element across two panels was woven with the primary screen's lattice and viewer on both halves. The issue calls this the "wrong lattice / looks around from the wrong camera" symptom.
Extension revision:
XR_DXR_weave18 → 19New, out-only, chained on
XrWeaveOutputDXR::next. The struct type isXR_TYPE_WEAVE_OUTPUT_RECT_PARTS_DXR = 1004999292, registered inopenxr_includes/openxr/README.md.Old callers see no change. A caller that does not chain the struct sends exactly the pre-v19 messages. A v19 caller on an older runtime gets the struct skipped, so it stays zero, which reads as "use the base eyes". The header, the spec section §5g plus the version-history row, and the
index.jsonsummary are all updated.python3 scripts/gen_extensions_index.py --checkpasses.Consumer contract (browser,
displayxr-browser-pvt)XR_DXR_weave.h(spec 19). Gate onextensionVersion >= 19only to expect parts; chaining is always safe.xrWeaveSubmitDXR(batch or v6), chain a zero-initialisedXrWeaveOutputRectPartsDXR(type = XR_TYPE_WEAVE_OUTPUT_RECT_PARTS_DXR) onXrWeaveOutputDXR::next. It is about 4 KB, so keep it off the stack in hot code.segmentCount == 0, render every rect fromXrWeaveOutputDXR::eyesexactly as today.segmentCount >= 1, for eachparts[i]:parts[i].rectRelativeof rectparts[i].rectIndexfromsegments[parts[i].segmentIndex].eyes. Use them for the next frame, the same one-frame lag as the base eyes.screenSizeMetersandscreenSize(px), with the part placed on the screen atparts[i].screenRect. This is the same split the per-segment views make for OpenXR apps (oxr_segment_views).rectRelativeis in rect pixels. Each SBS half holds the whole rect squeezed, so a part occupiesrectRelative.x/w ÷ 2inside each half. On v6, place it at the same window-relative position scaled by the mode's view scale in every tile.eyesValid == XR_FALSEfor a segment (typicallywoven == XR_FALSE, shown flat as the left view), render that part from the base eyes.generationto re-plan per-part render targets only when it changes. The eyes change every frame and do not bump it.xrWeaveSnapWindowRectDXR. It now snaps to the majority screen's lattice.segmentCount == 0.Tests
scripts\build_windows.bat build: clean. The one C4090 warning inoxr_session.cis pre-existing; that file is untouched.ctest -C Release: 111 of 114 pass. The 3 failures are the known-environmentaltests_oxr_view_space_mode_floor,_mode_pinnedand_mode_floor_off.tests_weave_segments(7 cases, 129 assertions):count 0and no parts (the single-DP path);weave_get_segmentsreply fitsIPC_BUF_SIZE, and two screens' different eyes survive the wire and land on the right parts.tests_ipc_proto.py: 14 tests OK. A new case pinsweave_get_segmentsas the last call andweave_submit's reply as unchanged; the earlier "last N calls" assertions were shifted by one.scripts\build_windows.bat test-apps:weave_rpc_probe_d3d11_winbuilds.cube_handle_gl_winandcube_zones_d3d12_winfailed only on a parallel texture-copy race in the post-build step, which is unrelated.Rig recipe (two 3D panels side by side, the primary on the left)
Use the existing present-owner probe,
test_apps/probes/weave_rpc_probe_d3d11_win. This PR adds a v19 log to it.scripts/push-runtime-pf.shand register the dev Leia plug-in if needed. Startdisplayxr-servicenon-elevated (explorer.exe "…\displayxr-service.exe").set XRT_FORCE_MODE=ipc && test_apps\build\bin\weave_rpc_probe_d3d11_win.exe --rect=full --size=1600x900.--rect=fullmakes the weave rect the whole client area, so it straddles with the window.segments: present-owner … woven per screen by weave_submit; segment DPs on the render device …. Alsosegments: created a segment DP for screen 0x… via create_dp_d3d11_for_screenonce the window touches the second panel.v19 per-screen: segments=0 … (one display processor: base eyes apply)tosegments=2 parts=2.segmentlines should show different display ids and each panel's own eyes; the second panel's tracker eyes will differ from the primary's.partlines should tile the rect at the seam.segments=0.segments: drag snap follows screen 0x…'s lattice (majority, #1884)at INFO. The window should land phase-correct on the second panel.touch %TEMP%\dxr_weave_dump_triggerdumps the woven handback (dxr73_weave_output.png).Open questions
sys->device(the render device) instead. That is where the woven handback lives and where the Service crash-loops serving a browser (present-owner) client on v2.8.0-112 — access violation in igd10iumd64 via SimulatedRealityDirectX during weave #1172 ingest DP already is, so it follows Amendment 1's rule that a segment DP lives where its target is. A DP on the output device could not write the handback under the Epic: weave/repaint next to scanout — output-device split for hybrid GPUs #918 split.XRT_MAX_SEGMENTS(2) screens is woven per screen but reported withsegmentCount 0(one eye set).snap_window_rectwithout a window. It falls back to the panel DP if not, which is the old behaviour. This needs checking on the rig with the Leia plug-in.🤖 Generated with Claude Code