DisplayXR Runtime v2.7.0
Highlights
One compositor pipeline and Windows-native app switching. The service now runs a single always-on multi-compositor with one display processor per panel — N concurrent IPC apps no longer mean N weavers fighting over the lens — and every IPC app is a first-class window citizen: it appears in the taskbar/Alt-Tab, focusing it gives it the display, launching it shows it, and the spatial shell composes only the apps launched inside it, so you can use any other app over a running shell without closing it.
Features
One always-on pipeline (#964)
- One compositor pipeline — always-on multi-comp, default presenter policy when no controller is attached, one DP per panel (#964) (#1003)
- Presenter strategies: service window / app window / client texture / present-owner; the #963 standalone↔workspace seam is gone
- The shell composes only apps launched under it (#964 Phase A)
- Park an
APP_HWNDwindow when it loses the panel; park (minimize) the service window instead of hiding it while hosted clients live (#964 Phase A)
Windows-native app switching (#1014 / #1017)
- Focus follows the OS foreground window (#964 Phase A)
- Launching an app takes the panel — the new-app focus rule (#964 Phase A)
- Foreground override — reach an IPC app without killing the shell; an outside app can take the panel while the workspace keeps running (#964 Phase A)
- Match the foreground by process, so engine apps resolve correctly, and restore a parked presenter that takes the panel (#1017)
- Every hosted client gets its own runtime window — Phase B (#1014)
Panel lease + queued transitions (#965 / #966)
- Panel lease — one mode owner, deny-with-reason, no latched replay, mode events only after the DP confirms (#961, #761)
- Mode/geometry transitions applied on the render thread via the S3 command queue (#966); present-owner submit contract (#965) (#1010)
Robustness
- Detect a lost D3D11 device at every create/present and exit for orderly relaunch; the DP is no longer driven after device removal; sticky present tokens (#1002) (#1009)
- Append-only display-processor vtable slot
set_window— with a matching vendor plug-in the panel re-binds in place on focus changes, with no weaver recreate and no 2D blip (#1008) (#1021). Ships with the paired Leia SR plug-in release. - Present watchdog — name the Present call that never returns (#1000)
- Log which D3D adapter was chosen, and why (#1000)
exit()/terminatetripwires — atexit stack logger + SEH guard at every thread entry (#950)- Plug-in loader refuses build-tree/worktree DLL paths; NULL-guard begin/end_feature (#952)
- Runtime-owned window phase-snaps its own drags via the DP vtable (#625) (#997)
DXR_QTRACE— an opt-in tracer for the whole head/view pose path- Legacy per-client path still available for one release via
DXR_LEGACY_STANDALONE=1(motion-to-photon measured at or better than legacy on both tested app shapes)
Pacing / throughput (#1019)
- Restore commit backpressure for pipeline clients — legacy WebXR ran unthrottled at ~300 Hz, causing judder and tearing; commits are now paced to the display (
DXR_COMMIT_PACE) (#1019) - App-window presenters default to frame-latency 2 on cross-adapter boxes (
DXR_APP_HWND_LATENCY) — 40 to 60 fps (#1019)
IPC hardening / capacity
- Explicit client classes — declared at connect, verified by the service, per-class quotas (#960)
- One focus authority — compositor focused slot canonical, no predict_frame promotion, server-side input focus (#962)
- Capacity —
IPC_MAX_CLIENTS8 to 32, runtime-admitted cap, reserved controller slot (#959) - Server-derived client identity — stop trusting
describe_client.pid(#954) - Authorize the controller-only workspace mutators (#955)
- No blocking pipe I/O under
global_state.lock; bound client-supplied allocs; check swapchain ids; cap the event queue (#956) - Resolve client id to xc off
global_state.lockfor the window handlers (#957) - Per-client
[HEALTH]telemetry from the mainloop (#951)
Input
- Presence poll off client threads; lock the qwerty integrator (#958)
- Rank providers like display processors — presence walks the hierarchy
- Hand-tracking source follows provider presence
- qwerty masquerades as the top provider's profile — hot-swaps go silent
- Ultraleap idle-disconnect watchdog — stop being a Leap client when no XR consumer polls (#941)
- Compose-from-copy for controller producers (#925 S5) (#940)
Fixes
- The #902 Vulkan queue-lock layer can never break
vkCreateInstance; its manifest now uses a loader-resolvable path (#1025) - Hosted world-absolute view chain keys on the head pose, not
workspace_mode— hosted view poses no longer lose standing height under an active workspace (#1014 follow-up) (#1024) - Per-client atlas submission atomicity — the single-frame tear window is shut (#1018) (#1020)
- Pace commits on an absolute deadline, not a duration (#1019)
CLIENT_TEXTUREweaves on its own thread — the render thread must never make an unbounded driver call for one client (#1017)- Exactly one window feeds qwerty — the active presenter's; freezing pose integration must not bank time (#1016)
- Every
process_atlassite owns the shared DP's state (#1016) - Parked windows restore, and a restored presenter keeps presenting (#1014)
- An UNPLACED slot is not a workspace tile — canvas is its presenter's rect (#1014)
- Workspace empty state keys on placed slots, not slot count (#964 Phase A)
- Present-owner transparency on the shared DP; the direct path resets viewport and scissor (#964 follow-ups) (#1013)
- One DP per HWND, ever — removes an SR WndProc-subclass crash class; late-weave governor samples only while the service window presents (#1012)
- Truthful
comp_multibanners;MULTI_MAX_CLIENTSexhaustion fails the create loudly (#1004) (#1011) - Close the runtime-owned window gracefully — ESC ends the session instead of losing it (#999)
- Restore the app's pipeline state after compositing; drop the pointless CPU fence wait (#996)
- Standalone/workspace transition dead ends + mainloop shm-push crash (#963)
- Monkey-test F1/F2 — no visibility demotion of standalone clients, controller policy only once the workspace is active, throttled layer errors, quiet plug-in refresh
- Monkey-test F3/F4/F5 — workspace enumerate lists only APP/PRESENT_OWNER, one-write log lines, standalone client names
cube_hosted_legacy_d3d12_winwrote sRGB into a UNORM-read atlas (#988)- WebXR bridge exits on
XR_ERROR_INSTANCE_LOST/SESSION_LOSTinstead of spinning on :9014 (#953) - Trampoline thread owns its :9014 listener; startup singleton (#975)
u_crash_guard: keep the stack-buffer length local to the Windows branch- Atlas capture dropped the bottom half of legacy frames
- WebXR got a world-absolute camera 1.6 m above its own poses
- Hosted apps over IPC lost the rig height — cube floated 1.5 m overhead
- Session end must not install 2D as the service-wide default mode (#762)
- An exception in the window proc must not kill the service
- Standalone present strobe — never clear an atlas slot a skipped blit will reuse
- Input: reconnect after a service drop; coalesce profile-change events
- Input: arbitrate the hand roles against provider presence, not registration
- Input: tracked hands ignored navigation and were stranded at the desk
- Ultraleap: a Leap unplugged while idle never handed the roles back
Docs
- Service architecture map (as built) + ADR-035 target architecture; Phase-1/2/3 update banners (#954-#959, #960/#961/#962, #963, #964, #966/#965, #1002, #967)
comp_multione-pipeline design note (#967) + docs index entries- D-9 focus follows the OS foreground; D-10 scoped, non-exclusive workspace (#964/#1014)
- One-pipeline design note — motion-to-photon A/B first pass (pipeline vs
DXR_LEGACY_STANDALONE=1) - ADR-035: record the confirmed decisions — DP stays in-process, wait on #943
- Corrected stale service/IPC claims found by the architecture review
- Chrome hot-swap freeze root-caused — three.js
XRControllerModelFactorystale cached model; three.js #34264 fixed upstream in r186 (masquerade still load-bearing)
CI / Build
- Opt CI into sim-input explicitly (
DXR_SIM_INPUT=1)
Other
- chore(versions): bump runtime to v2.6.3
Known issues
- Present-owner (browser) 4K windows can hitch on cross-adapter machines (#1019).
- Focused-presenter frame rate degrades with 4-5 concurrent clients (#1022).
- Under a foreground override the workspace controller receives no frame ticks (its cursor/UI pauses).
- Transparent/zones apps in forced-IPC mode without a workspace can present a blank window (fix in progress).