9 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 b0503eedb6 docs: move RECON entitlement-stub editor's note to a single top banner
Consolidate the two inline notes into one prominent note at the top of the doc, so
the "this stub approach was not carried into the project" framing is seen before any
of the entitlement-stub passages rather than only beside them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6sFYGXZPsq3v7xtcDES6g
2026-06-29 01:24:37 -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