Repository navigation
feat(d3d12): multi-screen segments + per-segment views for the in-process D3D12 compositor (M6 + M3) - #1879
Merged
Conversation
dfattal
force-pushed
the
feat/win-d3d12-segments
branch
2 times, most recently
from
October 9, 2026 10:01
af8fe03 to
8069830
Compare
…rigin (multi-screen M6) The D3D12 twins of the D3D11 per-screen slots, appended per ADR-020 with no XRT_PLUGIN_API_VERSION_CURRENT bump (ABI stays 5): - xrt_plugin_iface::create_dp_d3d12_for_screen, after create_dp_d3d11_for_screen; announced by XRT_PLUGIN_IFACE_HAS_CREATE_DP_D3D12_FOR_SCREEN, probed with xrt_plugin_iface_has_create_dp_d3d12_for_screen(). - xrt_display_processor_d3d12::set_present_origin, after get_background_preview; announced by XRT_DP_D3D12_HAS_PRESENT_ORIGIN, called through a struct_size-gated helper. Plus a D3D12 tolerates_resample() helper mirroring the D3D11 one. The D3D12 contract differs in one place: every segment records onto one command list, which carries no viewport/scissor a DP could inherit, so a screen-bound DP sets both from the canvas itself. sim_display implements both on D3D12 (screen-bound instance answers its own screen's metrics and confines viewport + scissor to the canvas) so the CI self-test keeps a complete sim-display. tests_stereo_camera pins the new iface tail; xrt_plugin_iface.md documents the Windows slots. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…gment views (multi-screen M6 + M3)
The in-process D3D12 compositor (the Unity display provider's path) gets
the pre-split D3D11 segment model:
- comp_d3d12_segments.{h,cpp}: the twin of comp_d3d11_segments — screen
table join, DP lifecycle with hysteresis, decide loop, primary-first
weave order, flat-2D fill. GPU work in D3D12 terms: per-screen crop
textures (COMMON -> COPY_DEST -> COMMON), each with its own slot in a
module-owned shader-visible SRV heap (descriptors are read at execute
time, so one slot cannot serve two DPs on one list), explicit source
barriers, viewport + scissor = segment before every DP.
- comp_d3d12_compositor_set_screens + d3d12_segments_tick at the weave
site: off zero-copy, the #918 split, the #1264 reroute, a zones /
Local2D canvas, and a back buffer that does not match the client area;
the window rect comes from the HWND in device px. Repaints take the
same path.
- M3: comp_d3d12_compositor_get_segment_metrics / set_view_routing, the
renderer's mosaic routing (projection layers per segment rect with the
tile's blend mode decided once; quads + equirect2 once per segment with
that segment's camera), comp_d3d12_renderer_blit_rect for the flat fill,
and a routed frame is never zero-copy.
- oxr: session create / xrLocateViews / xrEndFrame hand-offs for D3D12;
the Windows view-set capacity counts a D3D11 OR D3D12 factory
(oxr_segment_views_win_entry_has_dp, host-tested).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ti-screen M3)
Port of the cube_handle_d3d11_win M3 change: chain XrViewActivityStateDXR
+ XrViewDisplayBindingsDXR, render every view set the runtime hands out,
each at its display's segment rect inside its tile, and log the bindings
once per change ("view sets: ...") — the rig check's app-side proof.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
dfattal
force-pushed
the
feat/win-d3d12-segments
branch
from
October 9, 2026 10:14
8069830 to
9e0f412
Compare
This was referenced Oct 9, 2026
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.
What
Multi-screen segments (ADR-047 D2, M6) and per-segment views (M3) for the in-process D3D12 compositor — the path the Unity display provider runs on. The twin of #1857 / #1863 for D3D11, mirroring the pre-split D3D11 behaviour (the #918 split path is untouched; nothing in
compositor/d3d11/changes).ABI (append-only, no
XRT_PLUGIN_API_VERSION_CURRENTbump — ABI stays 5)xrt_plugin_iface::create_dp_d3d12_for_screenaftercreate_dp_d3d11_for_screen; announced byXRT_PLUGIN_IFACE_HAS_CREATE_DP_D3D12_FOR_SCREEN(sameCREATE_naming as the D3D11 / Vulkan macros), probed byxrt_plugin_iface_has_create_dp_d3d12_for_screen().xrt_display_processor_d3d12::set_present_originafterget_background_preview(slot 24); announced byXRT_DP_D3D12_HAS_PRESENT_ORIGIN, struct_size-gated helper. Plusxrt_display_processor_d3d12_tolerates_resample().tests_stereo_camerapins the new iface tail;docs/reference/xrt_plugin_iface.mddocuments the Windows per-screen slots.Runtime
compositor/d3d12/comp_d3d12_segments.{h,cpp}— the D3D11 manager's twin (screen join, hysteresis lifecycle, decide loop, primary-first weave, flat-2D fill). D3D12 specifics: every segment records onto the one weave command list; each screen's crop has its own slot in a module-owned shader-visible SRV heap (descriptors are read at execute time); explicit COMMON → COPY_* → COMMON barriers on the crops and the source (D3D12 compositor: per-frame ResourceBarrier before-state mismatches (debug-layer id 527) — suspected in editor resize DEVICE_HUNG #747); viewport + scissor = segment before every DP (and the DP sets both itself — a command list has nothing to inherit). No deferred-release list: every weave ends in a full queue wait.comp_d3d12_compositor_set_screens+d3d12_segments_tickat the weave site (repaints included). Not segmented: zero-copy, the Epic: weave/repaint next to scanout — output-device split for hybrid GPUs #918 split, the epic: in-process tier parity — panel-rate weave everywhere (VK / D3D12 to match d3d11-hybrid smoothness) #1264 reroute, a zones / Local2D canvas, a pinned session,DXR_SEGMENTS=0, and a back buffer that does not match the client area. Window rect = the HWND's client area in device px.comp_d3d12_compositor_get_segment_metrics/set_view_routing; renderer mosaic routing (projection layers per segment rect, the tile's CTS composition: projection layers are blitted opaque over the whole tile, wiping every layer submitted before them (QuadProjectionQuad / ProjectionQuadProjection FAIL) #1598 blend mode decided once; quads + equirect2 once per segment with that segment's camera);comp_d3d12_renderer_blit_rectfor the flat fill; a routed frame is never zero-copy.xrLocateViews/xrEndFramehand-offs for D3D12; the Windows view-set capacity counts a D3D11 or D3D12 factory (oxr_segment_views_win_entry_has_dp, host-tested — a D3D12-only plug-in used to count zero screens).cube_handle_d3d12_win: the cube_handle_d3d11_win M3 port (renders every view set at its segment rect, logsview sets: ...once per change).comp-segments.mdandroadmap/multi-screen.md.Tests
scripts\build_windows.bat build, thentest-apps): both exit 0.check_displayxr_app.pyon the D3D12 cube: clean.ctest -C Release: 100/103 pass; new/changedtests_oxr_segment_views,tests_stereo_camera,tests_comp_segmentspass. The 3 failures (tests_oxr_view_space_mode_floor,_pinned,_floor_off) are environmental on this box (they needSIM_DISPLAY_OUTPUT=quadto take on the registered DP) and fail identically on a peer worktree build without this change.Rig check (two monitors, sim_display or Leia)
feat/win-d3d12-dp-segmentsbuilt against this branch; sim_display needs nothing._package\run_cube_handle_d3d12_win.bat, drag the window so it straddles the seam between the primary (system-default) screen and the second one (at least 2 px on each side).%LOCALAPPDATA%\DisplayXR\DisplayXR_cube_handle_d3d12_win.*.log):segments: N screens, plug-in '…' — a window spanning monitors is woven per monitor (multi-screen M6, D3D12)(session start)segments: created a segment DP for screen 0x… ('\\.\DISPLAYn', plug-in '…') via create_dp_d3d12_for_screen(two DPs: the primary + this one)segments: D3D12 window x,y WxH -> …(INFO, the table)segments: D3D12 per-segment views routed — 2 segment(s) x 2 view(s) …(INFO, M3) and the diag(oxr): log the per-segment view-set decision once per change (multi-screen M3) #1870 WARNper-segment views: segments=2 capacity=2 active=… -> total=4; …(a0.000x0.000 msegment there means the screen has no physical size and the layout refused)view sets: routed [display 0x… views 0..1 at …] [display 0x… views 2..3 at …] (activeViewCount=4, rendering 4)segments: D3D12 window … is on the primary screen only — single-DP path, then after ~0.5 sretiring the D3D12 segment DP(INFO).DXR_SEGMENTS=0→ single DP,view sets: single.🤖 Generated with Claude Code