Repository navigation
feat(multi-screen): segments + per-segment views on the service / IPC path (stacked on #1878) - #1881
Merged
Merged
Conversation
dfattal
force-pushed
the
feat/win-segments-service-path
branch
from
October 9, 2026 09:44
1c53c8c to
57d8f9e
Compare
comp_d3d11_segments and the output composite unit it blits flat 2D through move into their own static library, linked by comp_d3d11 as before, so the D3D11 service compositor can segment IPC clients' windows without linking the whole in-process compositor (the comp_xbridge precedent). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
util/comp_segments_route.h (header-only, backend-agnostic): where one submitted view of a routed projection layer lands in the atlas mosaic (comp_segments_route_place, all-or-nothing validation, same rect mapping as the per-segment crop) and the generation-bumping publish of a segment table. oxr_segment_views_route_differs: the client's change-only send rule for an out-of-process compositor. Multi-screen M3 on the service path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The direct single-client pipeline (pipeline_default_policy_render) weaves an APP_HWND presenter whose window spans monitors through the client's own comp_d3d11_segments manager, made on svc_out_device (the output device under the #918 split): the panel DP on the primary screen's segment, windowless per-screen DPs (create_dp_d3d11_for_screen) on the others, flat 2D where no DP can weave. Opt-in per client (comp_d3d11_service_set_client_segment_screens, fed the service's own screen registry); a client that never opts in is woven by the single process_atlas exactly as before. Per-segment views: the last direct weave's table is published per client (fresh for 250 ms; eyes predicted at query time) and the client's routing lays a routed commit into the atlas as the mosaic (service_proj_view_blit_resolve, never zero-copy). One client's segment DPs at a time: a focus change releases the outgoing presenter's. Compose / workspace mode is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three calls appended to proto.json: compositor_segments_enable (the session's display pin; the service enumerates its own screens), compositor_get_segment_metrics (xrt_segment_metrics by value) and compositor_set_view_routing (xrt_segment_view_routing by value), with server handlers that are inert off the D3D11 service and client proxies. Both payloads are asserted to fit IPC_BUF_SIZE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Windows service session advertises the per-segment view-set capacity from the service's registry (the by-value copy; factory pointers only NULL-tested), enables segments at session create when that capacity is above 1, fetches the service's table in xrLocateViews and sends the routing change-only from xrEndFrame. A segment locate keeps its client-side Kooima FOVs and never takes the single-set server rig call. Single-screen boxes send nothing new. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests_segments_ipc: routed mosaic placement (incl. a 2D commit and an inconsistent routing), the change-only publish and send rules, and that the two wire messages fit one IPC buffer and carry their payload verbatim. tests_ipc_proto: the three calls are appended at the end of proto.json. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
comp-segments: Service / IPC path section; service-architecture: the direct pipeline's segment path; roadmap M6 status; ADR-047 Amendment 2 (the service owns the screens, only the direct pipeline segments, compose mode stays single-screen, table + routing by value). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Amendment 2 is the window handle following the majority segment (#1880), which lands first; the service / IPC path becomes Amendment 3 everywhere this branch names it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
dfattal
force-pushed
the
feat/win-segments-service-path
branch
from
October 9, 2026 09:59
57d8f9e to
3eba6fc
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.
Stacked on #1878 (
feat/win-segments-under-split) — merge that first; this branch is rebased on it and its diff againstmainincludes #1878's commits until then.Multi-screen segments (ADR-047 D2/D3) on the service / IPC path: an
_ipcclient composited bydisplayxr-service.exewhose window straddles two monitors is woven per screen (one DP per screen, each with its own canvas rect, present origin and, with per-segment views, its own viewer), exactly as the in-process D3D11 compositor does since #1857/#1863/#1878.Design
XR_DXR_win32_window_bindinghandle the service already presents into as theAPP_HWNDpresenter,fc->render.hwnd). The render thread reads its client area withGetClientRect+ClientToScreenin the per-monitor-DPI-aware service, which gives device px, the space the registry's monitor rects use. Both calls work cross-process and send no message. Same source ascomp_d3d11_service_get_client_app_window_metrics.enumerate_displays(target_screens/u_screen_info, plug-inget_display_info_for_monitor), whichxrEnumerateDisplaysDXRreaches over IPC today. The client sends only its session'sXrSessionDisplayBindingDXRpin (compositor_segments_enable). The IPC handler enumerates the service's own screens and hands the client compositor a heap copy, plus a copy of the system info (the DP registry), as in-processset_screensdoes.comp_d3d11_segmentsmanager per client. It is the in-process manager, split into a newcomp_d3d11_segsstatic lib (with the output composite unit it blits flat 2D through) so the service links it without the whole in-process compositor, following thecomp_xbridgeprecedent. It is built lazily on the render thread onsvc_out_device(the OUTPUT device under the Epic: weave/repaint next to scanout — output-device split for hybrid GPUs #918 split) with the samecreate_dp_d3d11_for_screenfactory slot. The panel DP, bound to the app's HWND, is the primary and keeps drag phase-snap. Only one client's segment DPs exist at a time: a focus change releases the outgoing presenter's set. Teardown runs underrender_mutex.pipeline_default_policy_render) with anAPP_HWNDpresenter.pipeline_segments_weavereplaces that frame's singleprocess_atlas. A hosted client presents into the service window on the panel. A present-owner orCLIENT_TEXTUREclient weaves on its own thread. A zones frame keeps the single DP. None of these is segmented.proto.json:compositor_get_segment_metrics(xrt_segment_metricsby value) andcompositor_set_view_routing(xrt_segment_view_routingby value). Both arestatic_asserted to fitIPC_BUF_SIZE, and the protocol stays append-only (a test pins the three new calls at the end). The service fills each segment's eyes at query time: the primary's from the panel DP, the others' from their segment DPs. A table older than 250 ms is not handed out, so a client that lost the panel locates one view set. The client-sideget_segment_metrics/set_view_routingare IPC proxies.oxr_session_locate_viewsthen runs unchanged, with two IPC-only differences: a segment locate keeps its client-side Kooima FOVs over the device's single-set answer, and it never takes the serverlocate_views_rigcall, which knows one view set. Routing is sent change-only fromxrEndFrame. The service lays a routed commit into the client atlas as the mosaic (comp_segments_route_place, the same rect mapping the crop reads). A routed frame never zero-copies.xrt_system_compositor_info(the factory pointers are service addresses and are only NULL-tested). On a box with two D3D11-DP screensPRIMARY_MULTIVIEW_DXRdoubles, as it does in-process.multi_compositor_renderkeeps one presenter, the service window on the panel, so a workspace window is never segmented and its table stays empty. Per-screen workspace presenters are a separate decision, recorded in ADR-047 Amendment 3.Not yet on the service path (follow-ups)
Files
src/xrt/compositor/d3d11/CMakeLists.txt: newcomp_d3d11_segslib (no source edits tocomp_d3d11_compositor.cpp/comp_d3d11_segments.*).src/xrt/compositor/util/comp_segments_route.h(new): routed placement and change-only publish.src/xrt/compositor/d3d11_service/{comp_d3d11_service.cpp,.h,CMakeLists.txt}: segment path, mosaic routing, per-client state, IPC-facing setters and getters.src/xrt/ipc/{shared/proto.json,server/ipc_server_handler.c,client/ipc_client_compositor.c,client/ipc_client.h}.src/xrt/state_trackers/oxr/{oxr_system.c,oxr_session.c,oxr_session_frame_end.c,oxr_objects.h,oxr_segment_views.h}.tests/tests_segments_ipc.cpp(new),tests/tests_ipc_proto.py,tests/CMakeLists.txt.comp-segments.md§ Service / IPC path,service-architecture.md§4.3,roadmap/multi-screen.mdM6, ADR-047 Amendment 3.Testing (win box, laptop panel only — no rig run)
scripts\build_windows.bat build: exit 0 (no new warnings).ctest -C Release: 101/104 pass. The 3 failures aretests_oxr_view_space_mode_{floor,pinned,floor_off}, which fail on this box independently of this change. The newtests_segments_ipc(7 cases, 81 assertions) and the extendedtests_ipc_protopass, as dotests_comp_segmentsandtests_oxr_segment_views.Rig check (forced IPC, two panels: laptop at (0,0), DS1 at (3840,0))
scripts\build_windows.bat build test-apps.explorer.exe C:\path\to\run_dev_service.bat. The service reads its own env: put anyDXR_*knob, e.g.DXR_SEGMENTS=0for an A/B, in that bat.%LOCALAPPDATA%\DisplayXR\DisplayXR_displayxr-service.*.log):segments: IPC client 0x… (pid N) enabled segments — 2 screen(s) in the registry, pinned display 0x0000000000000000segments: 2 screens, plug-in '…' — a window spanning monitors is woven per monitor (multi-screen M6, D3D11)segments: IPC client 0x… (pid N) — a window spanning monitors is woven per screen by the service's direct pipeline; segment DPs on the OUTPUT device 0x… (multi-screen M6, service path)segments: created a segment DP for screen 0x… ('…', plug-in '…') via create_dp_d3d11_for_screen — …DisplayXR_cube_handle_d3d11_win.*.log):per-segment views: segments=2 capacity=2 active=2 reported=4 -> total=4; [0] … [1] …(WARN, once per change).🤖 Generated with Claude Code