Repository navigation
feat(#336): several window-space UI layers at once (wsui slots) - #341
Merged
Merged
Conversation
byungjul
force-pushed
the
feat/wsui-multi-slot
branch
from
October 1, 2026 08:21
520bc4d to
ae7af5f
Compare
The native wsui registry had a single slot, so when two DisplayXRWindowSpaceUI components were enabled together (lenovo-avatar opens its radio and tuning HUDs on the same key) the last one to register won and the other never showed. Same on every backend. - wsui module: DXR_WSUI_MAX_SLOTS (4) entries; acquire/release_slot plus _slot variants of set_texture / set_layer / clear / get_pending. The slot-less API is kept and addresses slot 0. - session: per-slot state (ProviderWsui wsui[PS_MAX_WSUI]); create, getter (dxr_prov_get_wsui_bridge_slot), submit and teardown take a slot, and one window-space layer is submitted per registered slot. Layer array sized for zones + Local2D + all wsui slots. - Vulkan: one overlay kind per slot (DXR_PVK_OVERLAY_WSUI0 + N) and one copy render event per slot. - C#: each DisplayXRWindowSpaceUI acquires its own slot in OnEnable and releases it in OnDisable (which used to clear the one shared layer even while another HUD was still up). Falls back to the slot-less API on a native plugin without slots. Behaviour change on all backends: two or more enabled DisplayXRWindowSpaceUI components are now all composited (previously only the last registered one), and disabling one no longer clears the others. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A slot taken over by another component never shows the previous owner's last image: the Vulkan overlay remembers which registered texture its content was copied from (dxr_pvk_overlay_content_source) and submit only composites content from the texture registered NOW. Same check for Local2D. - One slot count: DXR_WSUI_MAX_SLOTS (displayxr_window_space_ui.h) now drives PS_MAX_WSUI, DXR_PVK_OVERLAY_COUNT, the per-slot render events and the overlay labels; the duplicate get_pending_slot externs are gone. - C#: a component that found every slot taken retries about once a second and appears when another HUD frees one; slots are only taken in Play mode (an [ExecuteAlways] edit-mode or prefab-stage instance would starve the play-mode ones); the legacy slot-less fallback is replaced by going inert (with a warning) on a native plugin without the slot API; the Vulkan-copy EntryPointNotFound disable now latches instead of re-arming every frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfattal
force-pushed
the
feat/wsui-multi-slot
branch
from
October 1, 2026 14:57
ae7af5f to
be788da
Compare
dfattal
pushed a commit
that referenced
this pull request
Oct 2, 2026
* chore(#332): put UpdateBakedHitColliders' doc comment back above it The Linux UpdatePointerFromInputSystem() method (#343) was inserted between UpdateBakedHitColliders' doc comment and the method, so the comment read as if it described the new method. Move the Linux method above the comment. No code change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(#332): round Linux PointerPosition/PointerDelta like macOS The macOS path rounds the cursor to whole window-client pixels (Mathf.RoundToInt on x and on the flipped y) before computing PointerPosition and PointerDelta; the Linux path (#343) did not, so Linux reported fractional pixels. Round the same way. Linux only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(#336): each overlay canvas has its own stage, not (0,100000,0) Since #342 every Local2D / window-space UI canvas gets its own stage from DisplayXROverlayStage (first at (0,100000,0), then 1000 units apart along x). The WindowSpaceUI sample README and router comment, window-space-ui.md and a leftover comment in DisplayXRWindowSpaceUI still said every canvas sits at (0,100000,0). Also note in DisplayXROverlayStage that the spacing assumes an overlay camera ortho half-width under 1000 world units. Comment/doc only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(#336): say how several window-space UIs stack Several DisplayXRWindowSpaceUI components are composited in slot order (lowest slot at the bottom), and each takes the lowest free slot on enable, so the draw order of overlapping HUDs follows enable/disable history, not anything the app sets. Document that (class doc, the slot-acquire comment, window-space-ui.md), advise keeping HUDs from overlapping, and note that under the DisplayXR shell only the first window-space layer is composited. Doc only, no behaviour change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
5 tasks
dfattal
added a commit
that referenced
this pull request
Oct 2, 2026
…ger washed out (#348) * fix(#347): request _SRGB swapchains on format-honest runtimes so colour isn't washed out Since runtime v2.21.0 (D3D11), v2.21.1 (D3D12) and v2.21.7 (Vulkan) the runtime believes the swapchain format (ADR-044 / INV-4.6, pinned by the Khronos CTS): an _SRGB swapchain holds encoded colour, and a UNORM one holds LINEAR values that it sRGB-encodes on the way to the panel. The plugin put encoded bytes into UNORM swapchains (the primary layer of every Gamma project, plus every wsui/Local2D canvas and the Gamma extra zones), so they were encoded twice and looked washed out. On a format-honest runtime (version from xrGetInstanceProperties, per graphics API; off under the runtime's own DXR_COLOR_LEGACY_UNORM_ENCODED=1 hatch): - Primary: _SRGB in both colour spaces. What Unity renders into is split from the swapchain format: a Linear project keeps encoding on store; a Gamma project renders into the UNORM sibling and the existing raw copy (CopyResource / CopyTextureRegion / vkCmdCopyImage) moves the encoded bytes into the _SRGB image unchanged. - wsui / Local2D (D3D11, D3D12, Vulkan): the _SRGB sibling; bridges stay UNORM. - Extra 3D zones (D3D, Gamma projects): the _SRGB sibling. Metal is not format-honest yet (ADR-044 section 7) and older runtimes keep the previous formats, byte for byte. Also refreshes the Windows x64 DLL, which predated #337/#339/#341. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(#347): read the runtime version from runtimeName when runtimeVersion is 1.x (Linux) Every Linux runtime shipped so far reports runtimeVersion 1.6.0 (DisplayXR/displayxr-runtime#1790), so the format-honest gate never engaged on Linux and apps stayed washed out. Fall back to the 'vX.Y.Z' tag in runtimeName when the major is < 2. Verified by Byungju on the DS1 (Ubuntu, RTX 4090, runtime v2.21.11): _SRGB swapchains (43 primary, 50 wsui/Local2D), raw bridge copies, no errors, and correct colour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
Several
DisplayXRWindowSpaceUIHUDs can now be shown at the same time. Before this change the native wsui registry had a single slot. When two components were enabled together, the last one to register won and the others never showed. lenovo-avatar opens its radio and tuning HUDs on the same key and only ever saw one of them, on every backend.Changes
displayxr_window_space_ui.*):DXR_WSUI_MAX_SLOTS(4) entries.acquire_slot/release_slot, plus_slotvariants ofset_texture,set_layer,clearandget_pending.ProviderWsui wsui[PS_MAX_WSUI]).dxr_prov_get_wsui_bridge_slot), submit and teardown take a slot, and one window-space layer is submitted per registered slot.DXR_PVK_OVERLAY_WSUI0 + N) and one copy render event per slot (DXR_EVENT_VK_OVERLAY_COPY_WSUI0 + N).dxr_prov_wsui_needs_copy/request_copybecame_slot.DisplayXRWindowSpaceUIacquires its own slot inOnEnableand releases it inOnDisable.OnDisableused to clear the one shared layer even while another HUD was still up.DisplayXRWindowSpaceUIcomponents are enabled, all of them are composited. Before, only the last one registered was.Testing
Linux, RTX 4090 + DS1, lenovo-avatar (whose app-side layout puts the two HUDs side by side without overlap):
native~/build-linux.shbuilds cleanly. The new slot exports are present in the.so.s_ps.wsui_*→ per-slot refactor with no logic change, but they haven't run on hardware.Part of #336
🤖 Generated with Claude Code