8 Commits
Author SHA1 Message Date
Daniel LynchandClaude Opus 5.5 da7dd08640 docs: fix runtime claim, stale header notes and dangling doc references
- ovrplugin_shim.h: runtime on Steam Frame is SteamVR (HOST.md), not Monado;
  drop the "Status: scaffold" line and the note that SetupLayer /
  GetLayerTexture2 await a 128-byte desc (implemented against the 108-byte
  ovrpLayerDesc); point RE-NOTES/SHIM-SCOPE at docs/research/.
- lever2-detect-skip-black-handoff.md lives in docs/research/, not analysis/.
- References to unpublished RE notes now say so instead of naming files that
  are not in the repo.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 22:44:34 -04:00
Daniel LynchandClaude Opus 5.5 28d610cb72 fix(vk): spec-valid queue detection; null all lazy PFNs on teardown
Queue detection probed vkGetDeviceQueue over families 0-3 x indices 0-3,
which is invalid for any queue the app did not create (VUID-00384/00385).
ovrp_Initialize5 passes only the VkQueue, and physical-device queue counts
bound what could exist, not what UE created. UE passes
FVulkanDevice::GetGraphicsQueue(), which it fetches as index 0 of the first
family with VK_QUEUE_GRAPHICS_BIT — so derive that (family,0) from
vkGetPhysicalDeviceQueueFamilyProperties and confirm it with one valid
vkGetDeviceQueue call.

xrr_vk_teardown now nulls every device/instance-level PFN. The dump, barcode
and copy-ring loaders only fetch a pointer when it is NULL, so a
Shutdown2 -> Initialize5 with a new VkDevice kept calling through the old
device's dispatch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 22:44:34 -04:00
Daniel LynchandClaude Opus 5.5 2088845a52 fix(input): derive hand validity every sync; seqlock the input snapshot
lvalid/rvalid were only ever set to 1, so a controller that went off or lost
tracking kept reporting a tracked pose frozen at its last position. Validity
is now recomputed each xrr_input_sync from xrLocateSpace (success AND both
ORIENTATION_VALID and POSITION_VALID), so lost tracking reports untracked.

The render thread writes the state while the game thread reads it; publish it
through the same cheap seqlock the view snapshot uses so a reader never pairs
one frame's pose with another frame's valid flag (or reads a torn pose).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 22:44:34 -04:00
Daniel LynchandClaude Opus 5.5 1d64595266 fix(xr): keep a timed-out swapchain image acquired and retry its wait
On XR_TIMEOUT_EXPIRED from xrWaitSwapchainImage, begin_frame released the
image. Per spec that release fails (CALL_ORDER_INVALID: the image was never
waited), so the acquire leaked and acquiredIndex desynced for good — the next
wait returns the oldest un-waited image, not the newly acquired one.

Track acquired-but-unwaited per swapchain (waitPending / depthWaitPending):
on timeout the image stays acquired, the layer (or its depth chain) is left
out of this frame's composition, and the next begin_frame retries the wait
without a new acquire. Teardown paths never release an unwaited image:
pipeline_reset leaves it for the post-restart retry (and now also releases
held depth/deferred images it used to leak), destroy_layer just destroys the
swapchain. These are the only two xrWaitSwapchainImage call sites.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 22:44:34 -04:00
Daniel LynchandClaude Opus 5 1f3dc40c07 docs+build: hygiene pass — close leak risk, de-drift docs, fix build prereqs
Repo hygiene round following a full review. No shim behaviour changes.

Leak risk:
- .gitignore: ignore CLAUDE.md (personal assistant-lane config, was one
  `git add -A` away from a public commit) and scratch_obj/.

Docs vs. reality:
- shim/README.md: rewritten. It described a pre-implementation skeleton with
  "core fns are TODO stubs returning -1005", three mutually inconsistent stub
  counts, and four completed milestones listed as open. Now carries the verified
  breakdown: 438/438 exports = 371 generated stubs + 46 core + 7 layers + 2
  Vulkan queries + 12 passthru trampolines.
- TESTING.md: dropped the self-contradicting "NOT yet" block (5 of 6 items were
  done or misstated, and contradicted the same file 45 lines above). Path B now
  points at tools/desktop-harness, which exists, instead of the orphaned
  shim/tests/harness.c. Path A prereqs marked as the record they are.
- HOST.md: corrected the runtime assumption. The OpenXR runtime inside Lepton is
  SteamVR (vendor/etc/openxr/1/active_runtime.json -> vrclient.so), not Monado.
  Favourable: SteamVR emulates Oculus Touch by default and advertises the
  XR_FB_foveation family, so the existing input and foveation paths should carry
  over. The old "remaining unknowns" are resolved by Lepton's published source
  and replaced with the items to check before a first Frame boot.
- README.md: same runtime correction.
- docs/research/RECON.md: the four passages prescribing an entitlement
  NOP/stub/bypass are corrected in place rather than merely disclaimed by the
  top banner, which they contradicted.

Build correctness:
- shim/build_android.sh: missing patchelf is now fatal. It warned and exited 0,
  producing a .so that cannot resolve the OpenXR loader at runtime.
- scripts/fetch_deps.sh + packaging/build_openxr_loader.sh: pin the OpenXR and
  Vulkan header versions (were tracking `main`), overridable via OPENXR_TAG /
  VULKAN_HEADERS_TAG; require cmake for the loader build.
- packaging/steamframe_patches.sh: use the apktool.jar that fetch_deps.sh
  downloads. Its prereq check demanded an `apktool` binary on PATH that the
  documented setup never provides, so it could not run after a clean setup.
- shim/gen_stubs.sh: it reads all_exports.txt, not shim_surface.txt; comment and
  emitted banner corrected. stubs.c regenerated (banner line only).
- shim/src/core.c: split seven `if (out) ...; return ...;` one-liners. Host
  build now compiles with zero warnings, down from seven.

Verified: host build 0 warnings; gen_stubs.sh output identical on regeneration;
bash -n clean on all edited scripts; pinned header/tarball URLs return 200 and
the tag tarball extracts to the expected directory name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 02:15:10 -04:00
Daniel LynchandClaude Fable 5 574f41a0e4 fix: deep-review round — legacy-ABI export, threading, and Vulkan robustness
- ovrp_GetTimeInSeconds: real export returning double (legacy direct-return
  ABI); the autogen ovrpResult stub left d0 uninitialized and the game reads it
- seqlock writer: fence the odd-mark before the data stores (torn-pose window)
- drain the frameState ring on STOPPING/shutdown (stale displayTime + permanent
  one-frame skew after every session pause)
- begin_frame FIFO bail: bound the wait (surface-teardown deadlock) and measure
  the deadline on CLOCK_MONOTONIC, immune to wall-clock steps
- passthru: pthread_once takeover + acquire/release PT_FWD pointer cache
  (first-use race could run the shim path mid-takeover)
- luma/dump/barcode readback disabled for non-4-byte swapchain formats
  (staging buffers assumed 4 B/texel; wider fallback formats would overflow)
- vkWaitForFences: honor timeouts everywhere; never reset a pending cmd buffer
- detect_ue_queue: keep the caller's queue family/index when detection fails
- xrr_get_node_pose: g_spaceLock vs the sitting/standing appSpace recreate
  (locate on a freed XrSpace)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 22:41:25 -04:00
Daniel LynchandClaude Opus 4.8 213115353b build: compile the Android shim at -O2 (was unoptimized)
The deployable arm64 artifact was built with no -O flag (-O0) while the host build
used -O2. For a latency/throughput-focused shim that's a real miss — bring the
Android build to -O2 to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6sFYGXZPsq3v7xtcDES6g
2026-06-29 00:57:06 -04:00
Daniel LynchandClaude Opus 4.8 a72a79ad29 Initial public release: OVRPlugin→OpenXR interoperability shim
An independent reimplementation of Meta's libOVRPlugin ABI on top of OpenXR, so
VrApi-era Meta Quest VR titles can run on non-Meta OpenXR runtimes (Monado,
Steam Frame) instead of being locked to Meta hardware. Original code only — no
Meta/Epic/Capcom binaries, headers, or assets. Includes a desktop harness that
drives the shim against Monado headless.

Scope/legal: interoperability; entitlement handling is out of scope. See README
for the legal/scope section and docs/ for the research trail and design notes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6sFYGXZPsq3v7xtcDES6g
2026-06-29 00:48:48 -04:00