Skip to content

feat(linux): 2D under the lens — SR Vulkan weaver composes the runtime's 2D over-layer - #301

Merged
dfattal merged 2 commits into
mainfrom
feat/linux-vk-2d-under-lens
Oct 6, 2026
Merged

dfattal merged 2 commits into
mainfrom
feat/linux-vk-2d-under-lens

Conversation

@dfattal

@dfattal dfattal commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

What

Port of #295 / #297 ("2D under the lens") to the Linux Vulkan display processor. The runtime's new VK slot set_overlay_2d (+ set_overlay_2d_filter_strength), DisplayXR/displayxr-runtime#1823, hands the DP the 2D over-layer of the next process_atlas. The DP forwards it to srWeaverSetComposeInputsVulkan, so the SR weaver composites it over the woven views in encoded space and band-limits it for the lens, instead of the runtime blending it post-weave (which aliases per eye).

DP (leia_display_processor_linux.c)

  • set_overlay_2d: accepts only an ENCODED layer in one of the four formats the SR contract names (R8G8B8A8 / B8G8R8A8, UNORM or SRGB), while the last frame was a 2x1 weave, transparency is not live (the post-weave alpha-gate would punch the layer out wherever the atlas is transparent), and the weaver can compose. Otherwise it returns false and the runtime keeps its post-weave blend.
  • Stateless per frame: the layer and strength are taken and cleared at the top of process_atlas, before any early return. They are re-checked against the frame itself (2x1, layer size == weave viewport), with one WARN if an accepted layer is dropped.
  • set_overlay_2d_filter_strength (v15) is consumed with the layer. Initialised to -1 (SR default), because the struct is calloc'd and 0.0 would mean "no filtering".
  • The target still leaves process_atlas in PRESENT_SRC_KHR (Linux VK DP: validation errors on the 3D weave path, and a WARN per resize in the 2D encode path #280).

Backend (leia_sr_linux_sdk.c, seam leia_sr_linux.h)

  • leiasr_lnx_compose_available() probes once per weaver with SR_COMPOSE_ORDER_2D_OVER (sticky), and logs the verdict once.
  • Order 1, not 3. 2D_OVER_COVERAGE writes the filtered coverage into the output alpha, which is alpha 0 over every 3D pixel. The D3D11 DP's alpha gate consumes it; nothing on Linux does, so order 3 would only make the 3D transparent. Order 1 writes alpha 1.0, like a weave without compose.
  • The compose fields ride leiasr_lnx_weave_input. Inputs are set immediately before srWeaverWeave, after every early return, so a layer is never left pending in the SDK holding a dead view. The v14 srWeaverSetComposeLayerUnchanged is sent every frame. The v15 srWeaverSetComposeFilterStrength is sent only on change (it is sticky in SR).
  • Render pass. SR filters the layer in prefilter render passes of its own, which it can record only before its output pass (vkweaver.cpp prepareCompose: canPrefilter = outputFramebuffer != VK_NULL_HANDLE). Inside our fb=0 pass it falls back to its inline kernel: the same lens box, but no prefilter cache, no v14 reuse and no motion mode. So a composing weave hands SR our cached framebuffer. It is built against our 0-dependency pass, the same shape as SR's RenderPassCache pass, so it is compatible by construction (the caller's framebuffer may come from a pass with dependencies, see Linux VK DP: validation errors on the 3D weave path, and a WARN per resize in the 2D encode path #280). Non-composing weaves are unchanged.
  • Diagnostics (A/B, not settings): DXR_LEIA_SR_COMPOSE=0 declines every layer, which brings back the old runtime blend. DXR_LEIA_SR_COMPOSE_INLINE=1 keeps the composing weave in our pass, i.e. SR's inline kernel.
  • Stub backend: compose_available always returns false.

Gates

  • Build: check_symbol_exists against the SR loader archive (the same probe shape as the snap, since the trampolines dispatch by slot index) for srWeaverSetComposeInputsVulkan + srWeaverSetComposeOrder, which defines DXR_LEIA_LNX_HAVE_SR_COMPOSE. The v14/v15 calls are probed separately. Unlike the snap this is optional: an SDK without it compiles the feature out. The DP slot itself is gated on the runtime header's XRT_DP_VK_HAS_OVERLAY_2D[_FILTER_STRENGTH].
  • Run time: an installed SR runtime that predates the calls answers SR_ERROR_FUNCTION_UNSUPPORTED, and a VK weaver that cannot compose answers SR_ERROR_FEATURE_NOT_SUPPORTED. Either way there is one WARN, the DP declines and the runtime blends post-weave.
  • CI: this compiles out today on both counts. The Linux SDK pin (SR_TAG 1.37.0.10693) predates the compose calls, and the Linux runtime pin (DXR_RUNTIME_GIT_TAG_LINUX v2.21.1) predates the VK slot. Enabling it in CI/.deb needs a Linux SDK built from the compose line and a runtime release carrying #1823.

GL

No GL display processor exists in the Linux arm (Vulkan-only), so SR slot 93 (srWeaverSetComposeInputsGL) has nothing to attach to here. It is a follow-up only if a GL DP is ever added.

Testing

  • Real SDK (/opt/leiasr, leiasr-runtime 1.38.0.34666+gcbf56e876a) against runtime #1823: configure reports SR weaver 2D compose (2D under the lens) ENABLED +v14 cache hint +v15 filter strength, and the build has no warnings in drv_leia_linux.
  • Compile-checked: stub weaver against #1823, and the real SDK against the pinned runtime v2.21.1 (slot compiled out).
  • test_lens_owner_linux: pass. test_compose_color_linux (lavapipe): PASS.
  • The on-panel check (DS1) is pending with David. Test producer: the runtime's weave_present_vk_linux HUD, a window-sized premultiplied overlay dma-buf submitted every frame over the 3D scene.

🤖 Generated with Claude Code

@dfattal

dfattal commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Hardware check on the DS1: native Wayland, Leia SR 1.38.0.41292 (Linux line, with the SR compose API), runtime #1823's branch build, weave_present_vk_linux, whose HUD is a window-sized 2D overlay over a rotating woven cube.

  • Compose on: the log shows SR weaver 2D compose ENABLED, then 2D overlay (1536x864) composited by the display processor INSIDE the weave and SR-owned output pass: prefilter passes + v14 reuse available. The HUD text was legible through the lens.
    • One frame during the window resize fell back to blended post-weave by the runtime, as the design allows.
  • A/B, DXR_LEIA_SR_COMPOSE=0: the runtime blends post-weave, and the HUD text is visibly fringed through the lens (David confirmed).

Pass. CI compiles the feature out until the Linux SR SDK pin carries srWeaverSetComposeInputsVulkan and the plug-in's Linux runtime pin reaches a release with runtime#1823.

🤖 Generated with Claude Code

dfattal and others added 2 commits October 5, 2026 23:47
…e's 2D over-layer

Port of #295/#297 to the Linux VK display processor. The runtime's new VK slot
set_overlay_2d (+ set_overlay_2d_filter_strength) hands the DP the 2D layer of
the next process_atlas; the DP forwards it to srWeaverSetComposeInputsVulkan so
the weaver composites it over the woven views in encoded space and band-limits
it for the lens, instead of the runtime blending it post-weave.

- DP: stateless per frame, consumed and cleared at the top of process_atlas
  before any early return. Accepts only an ENCODED layer in one of the four
  formats the SR contract names, while the last frame was a 2x1 weave,
  transparency is not live (the alpha-gate would punch the layer out) and the
  weaver can compose; re-checked against the frame itself (2x1, layer size ==
  viewport) with one WARN when an accepted layer is dropped. Still ends in
  PRESENT_SRC_KHR (#280).
- Backend: compose order probed once per weaver with SR_COMPOSE_ORDER_2D_OVER.
  Not 2D_OVER_COVERAGE: that writes alpha 0 over every 3D pixel, and nothing on
  Linux consumes the coverage. v15 strength forwarded on change only (sticky in
  SR), v14 unchanged hint every frame. The inputs are set immediately before
  srWeaverWeave so a layer is never left pending in the SDK.
- A composing weave hands SR our cached framebuffer (built against our 0-
  dependency pass, compatible with SR's by construction) so SR can record its
  prefilter passes before its own output pass; in our fb=0 pass it could only
  use its inline kernel. DXR_LEIA_SR_COMPOSE_INLINE=1 keeps the old pass,
  DXR_LEIA_SR_COMPOSE=0 declines every layer (on-panel A/B).
- Build gate: check_symbol_exists against the SR loader archive for
  srWeaverSetComposeInputsVulkan + srWeaverSetComposeOrder (optional, unlike
  the snap), plus the v14/v15 calls separately. Run-time gate: the trampolines
  answer SR_ERROR_FUNCTION_UNSUPPORTED on an older SR runtime -> one WARN, the
  DP declines, the runtime blends post-weave.

Compiles out in CI today: the Linux SDK pin (1.37.0.10693) predates the compose
calls and the Linux runtime pin (v2.21.1) predates XRT_DP_VK_HAS_OVERLAY_2D.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…se API

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@dfattal
dfattal force-pushed the feat/linux-vk-2d-under-lens branch from 87b6ae1 to d818a40 Compare October 6, 2026 06:47
@dfattal
dfattal merged commit b72cf9a into main Oct 6, 2026
16 checks passed
@dfattal
dfattal deleted the feat/linux-vk-2d-under-lens branch October 6, 2026 06:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant