Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9689da8
feat(lift): NeurD-backed 2D->3D lift module for the D3D11 DP
dfattal Sep 25, 2026
3f6f00e
feat(lift): wire the four NeurD lift slots into the D3D11 DP
dfattal Sep 25, 2026
5bf1544
docs(lift): NeurD lift architecture, threading, licensing, bridge, kn…
dfattal Sep 25, 2026
5a96158
fix(lift): caps never waits behind an in-flight convert
dfattal Sep 25, 2026
8ce86fe
fix(lift): match the runtime's landed lift contract (xrt_dp_lift.h)
dfattal Sep 25, 2026
8d39657
chore(lift): assert lift mode/state values against the runtime's
dfattal Sep 25, 2026
cb6537a
refactor(lift): build against the real NeurD headers, fetched from pr…
dfattal Sep 25, 2026
3f4dfc5
feat(lift): lift-only D3D11 DP factory + resync to the final lift header
dfattal Sep 25, 2026
d449868
fix(lift): log NeurD's activation/init callback lines at WARN until R…
dfattal Sep 26, 2026
d911a98
feat(lift): run on NeurD 0.3.11+ — get_dx_device optional, own bridge…
dfattal Sep 26, 2026
9b6114f
feat(lift): DXR_LEIA_LIFT_INTERACTIVE_MIN — opt-in interactive gate f…
dfattal Sep 26, 2026
c729013
fix(lift): DEPTH polarity — NeurD is near=high, the spec's RELATIVE i…
dfattal Sep 26, 2026
e8f65d7
fix(lift): DXR_LEIA_LIFT_INTERACTIVE_MIN calls the table slot directl…
dfattal Sep 26, 2026
9b7af2e
fix(lift): NeurD cannot tile beyond SBS through the public API — drop…
dfattal Sep 26, 2026
a4468c0
feat(lift): lift knobs from HKLM\SOFTWARE\DisplayXR\Leia\Lift (env st…
dfattal Sep 26, 2026
e036d3f
feat(lift): VideoModel knob -- pick NeurD 0.4.6's metric video model
dfattal Sep 27, 2026
8a73cd9
feat(lift): log which viewpoints a convert used (tracked / explicit /…
dfattal Sep 27, 2026
cda7f99
feat(lift): DepthGain knob, default 2.0 -- NeurD gain = strength x De…
dfattal Sep 27, 2026
874a553
fix(lift): never pass the tracked eye HEIGHT to NeurD (vertical paral…
dfattal Sep 27, 2026
ad147ee
feat(lift): Dilate knob, default 2 (NeurD's own default is 3)
dfattal Sep 27, 2026
f86015d
build(windows): pin the runtime to v2.22.0 — first release with the D…
dfattal Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ jobs:
# Read with LEIALOFT_GITHUB_TOKEN — the same secret the Android arm uses
# for LeiaInc/CNSDK. Fork PRs have no secret and cannot build this arm.
SR_SDK_REPO: LeiaInc/SR-SDK-Windows-Releases-Internal-Public
# NeurD headers for the 2D->3D lift module (docs/lift-neurd.md), fetched
# from the PRIVATE LeiaInc/media_sdk repo into the gitignored
# NeurD-SDK-<ref>/include -- never committed. Pin a media_sdk release tag.
# KEEP IN SYNC with scripts/build-windows.bat (check_sr_pins.py asserts).
NEURD_SDK_REF: v0.4.6
NEURD_SDK_REPO: LeiaInc/media_sdk
GH_TOKEN: ${{ github.token }}
# SourceForge serves a bot-check page to CI runners, so vcpkg's pthreads
# port (vcpkg_from_sourceforge) fails its hash on every mirror. This
Expand All @@ -103,7 +109,7 @@ jobs:
# regression originally).
# #734: runtime v2.0.0 (a8f6e74f) ships the XR_EXT_* → XR_DXR_*
# extension rename this plug-in's headers now use (ABI unchanged, v4).
RUNTIME_REF: v2.16.9
RUNTIME_REF: v2.22.0
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -180,6 +186,21 @@ jobs:
if (-not (Test-Path "$env:SR_V2_DIR/$f")) { throw "SR v2 SDK missing $f" }
}

# SOFT: without the headers the lift module compiles out and the plug-in
# is otherwise identical, so a missing token or an unreachable repo must
# not fail the build -- it is surfaced as a warning annotation instead.
- name: Fetch NeurD headers
if: needs.DetectChanges.outputs.docs_only != 'true'
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.LEIALOFT_GITHUB_TOKEN }}
run: |
./scripts/fetch-neurd-headers.ps1 -Repo $env:NEURD_SDK_REPO -Ref $env:NEURD_SDK_REF -Dest "NeurD-SDK-$env:NEURD_SDK_REF"
if ($LASTEXITCODE -ne 0) {
Write-Host "::warning::NeurD headers not fetched ($env:NEURD_SDK_REPO@$env:NEURD_SDK_REF) -- this build ships WITHOUT 2D->3D lift."
exit 1
}

# The plug-in CMake adds the runtime as a subdirectory, so we need
# all the runtime's own build prereqs (vcpkg, Vulkan SDK, OpenXR
# loader). Same shape as the runtime's build-windows.yml.
Expand Down Expand Up @@ -282,6 +303,8 @@ jobs:
env:
LEIASR_SDKROOT: ${{ github.workspace }}/LeiaSR-SDK-${{ env.SR_TAG }}-win64
LEIASR_V2_SDKROOT: ${{ github.workspace }}/${{ env.SR_V2_DIR }}
# Read by src/drv_leia/CMakeLists.txt; absent dir => lift compiles out.
NEURD_SDK_ROOT: ${{ github.workspace }}/NeurD-SDK-${{ env.NEURD_SDK_REF }}
run: |
cmake -S . -B build -G "Ninja Multi-Config" `
-DDXR_RUNTIME_SOURCE_DIR="${{ github.workspace }}/displayxr-runtime" `
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ __MACOSX/
# Fetched SR SDK (not committed; downloaded by CI / scripts/build-windows.bat)
LeiaSR-SDK-*/
simulatedreality-SDK-*/
# Fetched NeurD headers (Leia-private; scripts/fetch-neurd-headers.ps1)
NeurD-SDK-*/

# Installer artifacts (built into _package/)
DisplayXRLeiaSRSetup-*.exe
Expand Down
10 changes: 10 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ ADR-020 spec: [`displayxr-runtime/docs/adr/ADR-020-plugin-abi-policy.md`](https:
| `src/drv_leia/leia_display_processor*.{cpp,h}` | Per-API display processors (D3D11, D3D12, GL). Implement `xrt_display_processor_<api>` vtables; the runtime's compositor invokes them per-frame. |
| `src/drv_leia/leia_sr_*.{cpp,h}` | SR SDK weaver wrappers. The SDK throws `std::runtime_error` as routine internal control flow (~11/frame in some paths) — every call wrapped in try/catch. |
| `src/drv_leia/leia_bg_capture_win.{cpp,h}` | WGC background capture for compose-under transparency (Leia transparency model). |
| `src/drv_leia/leia_lift_neurd.{cpp,h}` | 2D→3D lift slots on the D3D11 DP, backed by a dynamically loaded NeurD.dll (absent ⇒ caps unavailable, nothing loaded). Compiles only with the private NeurD headers (fetched at build time, below) AND runtime headers with `XRT_DP_D3D11_HAS_LIFT`; otherwise the slots stay NULL. See [`docs/lift-neurd.md`](docs/lift-neurd.md). |
| `src/drv_leia/leia_edid_probe.c` | EDID-based hardware detection — answers "is a Leia display attached?" before the SR SDK initializes. |
| `src/drv_leia_linux/leia_sr_linux.h` | **Linux weaver-backend seam** — interface shaped 1:1 by `docs/leia-linux-sdk-contract.md` (every declaration cites its R-* requirement). Track B implements it against the real SDK. |
| `src/drv_leia_linux/leia_sr_stub.c` | Track A stub backend: canned panel info + passthrough SBS blit, `TODO(Track B)` at every body. |
Expand Down Expand Up @@ -134,6 +135,15 @@ run by `.github/workflows/lint.yml` on every PR, asserts all five pins
declared exactly once and identically in both files, and that
`SR_V2_TAG`/`SR_V2_DIR` name the same SR v2 build.

**NeurD headers (2D→3D lift) follow the same rule.** They are Leia-private
and come from the private **`LeiaInc/media_sdk`** repo at `NEURD_SDK_REF`
(pinned next to the SR pins in both files, also checked by
`check_sr_pins.py`), fetched by `scripts/fetch-neurd-headers.ps1` into the
gitignored `NeurD-SDK-<ref>/`. **Never commit or mirror them.** Your `gh`
account (and CI's `LEIALOFT_GITHUB_TOKEN`) needs read access to
`media_sdk`; without it the fetch fails SOFT and the plug-in builds without
lift. Details: [`docs/lift-neurd.md`](docs/lift-neurd.md).

### Linux
```bash
./scripts/build-linux.sh # Track A stub: .so + displayxr-cli, stage manifest, selftest
Expand Down
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,13 @@ endif()
# This plug-in MUST be built against headers that ship the matching major,
# or the runtime will log "ABI major mismatch — plugin_api=N, runtime
# expects M ... skipping (ADR-020 rule 3)" and fall back to sim_display.
# v2.22.0 (from v2.16.9): the first runtime that ships the D3D11 DP lift slots
# (XRT_DP_D3D11_HAS_LIFT, runtime#1781) and the lift-only factory
# (XRT_PLUGIN_IFACE_HAS_D3D11_LIFT_FACTORY). Appended and struct_size-gated,
# plug-in ABI still v5; an older pin compiles the NeurD lift module OUT.
# The rule-5 CI self-check below asserts this value equals the workflow's
# runtime checkout ref so the two can't drift.
set(DXR_RUNTIME_GIT_TAG "v2.16.9" CACHE STRING
set(DXR_RUNTIME_GIT_TAG "v2.22.0" CACHE STRING
"Runtime git ref to fetch. Must equal the workflow's runtime checkout ref (rule-5 CI check enforces).")
# Linux carries its own pin so it can move independently of the Windows
# installer's derived MIN_RUNTIME_VERSION (same reason as _ANDROID below).
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ Leia is the first 3D-display vendor integrated into DisplayXR. This directory do
| Display processor (per API) | `leia_display_processor.{cpp,h}` (base), `leia_display_processor_d3d11.{cpp,h}`, `leia_display_processor_d3d12.{cpp,h}`, `leia_display_processor_gl.{cpp,h}` |
| Weaver (per API) | `leia_sr.{cpp,h}` (base + eye tracking), `leia_sr_d3d11.{cpp,h}`, `leia_sr_d3d12.{cpp,h}`, `leia_sr_gl.{cpp,h}` |
| Background capture (transparency) | `leia_bg_capture_win.{cpp,h}` |
| 2D→3D lift (NeurD, D3D11) | `leia_lift_neurd.{cpp,h}` (+ private NeurD headers fetched at build time) |
| Shaders | `shaders/` |

## Docs in this directory

- **[Weaver internals](weaver.md)** — DX11 / DX12 / OpenGL / Vulkan weaver creation, inputs, weave() flow, DPI handling, phase math.
- **[Transparency model](transparency.md)** — current primary path: WGC compose-under-bg on D3D11 / D3D12 / Vulkan. Replaces the older chroma-key approach for those APIs.
- **[Chroma-key overlay (legacy / OpenGL fallback)](chroma-key-overlay.md)** — fallback path; still the only transparency path on the Leia OpenGL DP.
- **[2D→3D lift via NeurD](lift-neurd.md)** — the D3D11 DP's `lift_*` slots: dynamic NeurD.dll load, one-per-process activation (licence network failure = *activating*, retried), the shared-texture device bridge to NeurD's own D3D11 device, tracked-eye → NeurD viewpoint mapping, the `DXR_LEIA_LIFT*` knobs, and how to verify with `displayxr-cli lift caps|probe`.
- **[Late latching](late-latching.md)** — which backends implement it (D3D11/GL automatic, VK needs our submit hook, D3D12 is a stub), what `srWeaverIsLateLatchingEnabled` hides, the once-per-frame / deferred-context contract from the shipped header, and the dot test — including why `pattern = 450` makes it lie.
- **[SR panel readiness and late geometry](sr-readiness.md)** — the boot race (SR "default display" until the FPC serial link answers; never while the panel sleeps), the two readiness signals that actually work (`Global\sharedDeviceSerialMemory` count byte, a *fresh* valid display handle), the ONE shared startup budget (`DXR_LEIA_SR_READY_TIMEOUT_S`, default 20 s), the 1 Hz late-identification watcher that re-derives geometry and updates the live head device in place, and the `get_display_info` contract with the runtime (#266).
- **[Window phase snapping](window-phase-snapping.md)** — the SR weaver's automatic `WndProc` subclassing for lenticular phase alignment during window drag (Windows), and the resolved `WndProcDispatcher` race.
Expand Down
Loading
Loading