466 Commits
Author SHA1 Message Date
simplysanatori ea1460bddb Merge branch 'lane/Z' into native v0.9.0-alpha.1 2026-10-16 02:48:54 -04:00
simplysanatoriandClaude Fable 5.1 051cfc9dfe release: allowlist the bundled toolchain and translator for the tarball's boundary and privacy checks
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-16 02:48:54 -04:00
simplysanatoriandClaude Sonnet 5.5 b232483623 Wrapper: never start the panel recorder after the game is gone, stop it on every exit path; add test
The recorder subshell slept 8 s and then started even when the game had died at 3 s, and kept
recording the headset for hours. It now starts only if the game is alive, runs in its own session,
and is stopped (SIGINT, bounded wait, TERM, KILL, pkill) on game exit and on TERM/INT/HUP, with a
log line saying which path ran.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 02:48:37 -04:00
simplysanatoriandClaude Fable 5.1 51fb6268a1 0.9.0-alpha.1 pre-release: README in its final shape (status, the double image, what has been done, performance), release notes, changelog, technical notes, untested list; wrapper defaults KARTFRAME_END_PHASE=after
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-16 02:43:09 -04:00
simplysanatoriandClaude Fable 5.1 b2aea99bef perf: session-h20 results (after-lock clean but one refresh late; before unreachable; the clean probe ends at the default phase, so phase alone is not the cause)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-16 02:13:23 -04:00
simplysanatoriandClaude Opus 5.5 34c16e95be perf: session-h20 (end phase after / before / 4000 control), DEV.md lane X, mock results
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:59:44 -04:00
simplysanatoriandClaude Opus 5.5 1fa087d47c mock: MOCK_XR_ALIGN_US wake-up grid, stub update window (STUB_UPDATE_MS), mockrun runs the grid publisher with KARTFRAME_END_PHASE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:59:44 -04:00
simplysanatoriandClaude Opus 5.5 b849ada211 pacing: KARTFRAME_END_PHASE=after|before (test only): end locked to the published compositor grid, fixed-delay fallback, 10 s achieved-phase log, 4 pairs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:59:44 -04:00
simplysanatoriandClaude Opus 5.5 95dd11233a vrtiming.py: publish the compositor grid for KARTFRAME_END_PHASE (vsync in CLOCK_MONOTONIC, period, update start/end percentiles; 64-byte record, atomic rename, 0.1 s polls)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:59:44 -04:00
simplysanatoriandClaude Opus 5.5 9bfea79f14 perf: LANE_X.md (session 19 per frame: ends never before the update start; the edge is the update end) and phase.py view C, _RAW clock, frame-ready check fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:42:06 -04:00
simplysanatoriandClaude Fable 5.1 5322233f1d perf: session-h19 results (clean vs doubled 4 ms launches separated by the end's phase against the compositor's update window)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-16 01:31:41 -04:00
simplysanatoriandClaude Opus 5.5 6ab24c86af perf: LANE_W.md (clock matching, the end lock design and risks); session-h19 env files and README
Two launches at KARTFRAME_END_DELAY_US=4000 with KARTFRAME_VRTIMING_FRAMES=1, so a
clean and a doubled launch at the same delay can be compared by phase.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 00:34:30 -04:00
simplysanatoriandClaude Opus 5.5 7074f4758d XRF lines: wake-up, release and display time in CLOCK_MONOTONIC (m= r= t=)
m= is the wake-up in CLOCK_MONOTONIC ms (the end is m + e), r= the eye releases
after the wake-up (-1 on a repeat), t= the predicted display time converted with
xrConvertTimeToTimespecTimeKHR; an 'XRF clock:' line says how. Lines the app's
timeline up with vrframes.log (frame/tools/phase.py). DEV.md: lane W section.
Mock (END_DELAY 4000, MOCK_XR_TIME_OFFSET_S=5): ok, offset 5000 ms removed,
r = e - 0.01 ms; ctest 32/32.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 00:34:30 -04:00
simplysanatoriandClaude Opus 5.5 a538cd7eff phase.py: where the app's end lands in SteamVR's compositor frame, per launch
Reads vrframes.log and the XRF lines of a session folder: SteamVR's own app
timings against its vsync reference (frame ready, poses ready, margin to the
compositor's update start), and the app's wake-up, end, release and display
time minus the nearest compositor anchor through the P-line clock offset,
with 0.25 ms histograms and a per-second drift table. openvr-stub.c: a fake
libopenvr_api.so to exercise vrtiming.py's frame mode without SteamVR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 00:29:36 -04:00
simplysanatoriandClaude Opus 5.5 8816fe9a7d vrtiming: KARTFRAME_VRTIMING_FRAMES=1 logs every compositor frame to vrframes.log
One F line per compositor frame (de-duplicated by index, the newest two of each
poll held back), a P line per poll tying SteamVR's system time to CLOCK_MONOTONIC
through GetTimeSinceLastVsync, G lines for missed frames. SIGTERM now ends the
loop cleanly so both logs are flushed. KARTFRAME_STEAMVR_DIR picks the library
(tests). Checked against a stub libopenvr_api (120 Hz, no gaps over 4 s).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 00:26:38 -04:00
simplysanatoriandClaude Fable 5.1 960e3f11c4 perf: session-h18 results (4.0 ms not clean on repeat; the band is not fixed to the app's wake-up)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-16 00:19:50 -04:00
simplysanatoriandClaude Fable 5.1 8055bc5048 perf: session-h17 results (2.5 ms ends were bimodal, 6 ms bad for the right eye); session-h18 band-mapping env files (4000, 4500, 3500)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-16 00:10:36 -04:00
simplysanatoriandClaude Fable 5.1 0ddc778b23 perf: session-h16 results (ending the frame 4 ms after the wake-up removes the doubling); session-h17 delay sweep env files
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 19:58:14 -04:00
simplysanatoriandClaude Sonnet 5.5 2ca6ebedc8 pacing: KARTFRAME_END_DELAY_US test switch (frame ended N us after the wake-up, next set started before the sleep, 4 eye pairs)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-15 17:20:45 -04:00
simplysanatoriandClaude Fable 5.1 7601f392b9 perf/session-h16: launch 2, set render start delayed 4 ms after the wake-up
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 16:50:52 -04:00
simplysanatoriandClaude Fable 5.1 1ad004ba19 perf: session-h15 results (90 Hz and 1200 px both doubled: GPU load size and refresh rate ruled out); session-h16 env (thread priority boost and uclamp off)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 16:49:43 -04:00
simplysanatoriandClaude Fable 5.1 791be71dd1 perf: session-h14 headset results (desktop present and release backlog ruled out; drained queue cleared the left eye only); session-h15 env files (90 Hz, 1200 px eyes); wrapper KARTFRAME_EYE_PX
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 15:26:44 -04:00
simplysanatoriandClaude Opus 5.5 4fe9c0f03f perf: LANE_U.md (release ordered correctly, verdict B; ranked candidates) and session-h14 (no desktop swapchain; release idle)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 13:46:22 -04:00
simplysanatoriandClaude Opus 5.5 e4df6be3fa KARTFRAME_RELEASE=idle: drain Dawn's queue before each set's releases and its xrEndFrame (headset A/B)
Default unchanged. With idle, vkQueueWaitIdle under the queue guard right before
xrReleaseSwapchainImage of the eye pairs and before xrEndFrame, so SteamVR's
client submissions there never wait behind our next set's GPU work (the probe,
clean on the headset, had nothing queued at those points). Logs the drain's
cost every 10 s. DEV.md lines for the switch and the mock's new lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 13:29:44 -04:00
simplysanatoriandClaude Opus 5.5 dab2dd23d0 xrmock: strict release check (bytes at release vs next acquire) and release-queue latency per swapchain
The exact check's second sample is taken once an empty submission made at the
release completed, so it could not see work queued after the release. The new
strict check compares the image's bytes at its release with its bytes at its
next acquire (no queue involved). A waiter thread now times each release's
empty submission: how long a submission made inside xrReleaseSwapchainImage
(as SteamVR's client makes) waits behind the app's queued GPU work, per
swapchain and frame parity. Both only with MOCK_XR_BUSY_MS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 13:21:05 -04:00
simplysanatoriandClaude Fable 5.1 4a582ddd29 perf/session-h13: headset results (all six replay cases clean)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 13:08:31 -04:00
simplysanatoriandClaude Fable 5.1 bc320f84a5 session-h13 replay-case.sh: drop the launcher's arguments when run from the queue (xrprobe exited 2 on --oom-score-adjust)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 12:55:17 -04:00
simplysanatoriandClaude Opus 5.5 4ab88a166b Session 13 ready: recording notes (61 s, standing case = first 168 sets), replay launch recipe and owner routine, mock verification (replaycheck.py), DEV.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:31:55 -04:00
simplysanatoriandClaude Opus 5.5 84ee01956d xrprobe --replay: KartFrame's recorded race eye images at their recorded poses (session 13 cases), replay-case.sh, queue.sh, run-probes PROBE_SET=replay / PROBE_MOCK=1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:22:15 -04:00
simplysanatoriandClaude Opus 5.5 e3b7439117 xrmock: MOCK_XR_SWAY's still head only when a start time is given (the default sway unchanged for every time)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:46:09 -04:00
simplysanatoriandClaude Opus 5.5 285e608713 Lane S: the race eye images are clean in the mock (zigzag 0 % per eye, standing and driving); session-h13 xrprobe replay plan
frame/perf/LANE_S.md: 240-set windows of consecutive released eye images in the scripted race (head
still, standing with a 25 deg sway, driving), H7's zigzag rule per eye 0 % at two GPU loads while an
injected period-2 jump is flagged in 99-100 % of moving sets; no stale image, no eye difference.
frame/perf/session-h13/README.md: recorded race images through GalaxyFrame's loop (xrprobe --replay,
to write), cases for the content phase, KartFrame's pair rotation and race quad.
mockdump/dumprace.sh reproduces the recording; DEV.md lists the new mock switches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:45:51 -04:00
simplysanatoriandClaude Opus 5.5 f0fa6323a9 xrmock: MOCK_XR_DUMP_QUEUE (dumps without stalling the app: blit down, queue, write when the dumps pause); zigzag.py view and scene tracks
The stalling dump read every image back inside xrReleaseSwapchainImage and skipped about nine
refreshes in ten, so consecutive sets never existed. With the queue every set of a 240-set window
is dumped (end after wake-up p99 1.1 ms during the windows), and index.txt carries each image's
stamp (eye, display time, scene words), decoded from the stamp rows copied beside it.
zigzag.py: H7's rule on two tracks per eye (view: columns of the upper image; scene: the
track-side strips moving apart), the scene stamp's steps, eye phase and a lagdiff.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:41:03 -04:00
simplysanatoriandClaude Opus 5.5 488df49c41 xrmock: MOCK_XR_SWAY (sway size, period, start), press hold/until, dump index with stamps; mockdump/zigzag.py
Lane S tooling to test the panel zigzag on the mock's released eye images: the head's sway can be
made larger and held still until a given time, a scripted press can be held (driving) and can stop,
and MOCK_XR_DUMP writes index.txt with each image's eye and stamped display time. zigzag.py applies
H7's rule, a lagdiff and the eye phase per dump window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:19:27 -04:00
simplysanatoriandClaude Fable 5.1 62c357a2c8 perf/session-h12: headset results (pose check, one-ahead lateness, fresh poses, panel zigzag per eye and over time)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 06:12:08 -04:00
simplysanatoriandClaude Opus 5.5 6779476781 perf/session-h12: lane R's plan (measure, one ahead, fresh poses) and mock results
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:33:51 -04:00
simplysanatoriandClaude Opus 5.5 de92c3891c xrmock fresh-pose check: accept any locate for the display time that gave the layer's poses (equal floats at the sway's turning points)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:26:29 -04:00
simplysanatoriandClaude Opus 5.5 17c2a46f4b DEV.md: lane R switches
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:55:25 -04:00
simplysanatoriandClaude Opus 5.5 34dcb0e4db KARTFRAME_SUBMIT_POSE=fresh; xrmock MOCK_XR_STAMP=fresh checks fresh-pose layers against their own display time's locate
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:55:13 -04:00
simplysanatoriandClaude Opus 5.5 4dca761b8f KARTFRAME_AHEAD_REFRESHES=1: start the next set at the wake-up before ending the frame (GalaxyFrame's order), 4 pairs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:54:30 -04:00
simplysanatoriandClaude Opus 5.5 01a2e0bdc1 Pose check at every xrEndFrame (GalaxyFrame's notePoses), prediction distance, session-report rows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:53:06 -04:00
simplysanatoriandClaude Fable 5.1 fd266ec2b8 DEV.md: lane Q switches
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-14 16:13:28 -04:00
simplysanatoriandClaude Opus 5.5 c494058b39 perf/session-h11: lane Q's plan (race quad launch, first-write barrier launch) and mock results
Replaces lane P's one-launch plan. Mock: 0 errors, 0 of 42792 releases changed
after the GPU, stamps and end times exact, every race frame projection + quad,
validation layer clean, race timing unchanged A/B.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:11:19 -04:00
simplysanatoriandClaude Opus 5.5 6596f27cf2 Race quad (KARTFRAME_RACE_QUAD) and GalaxyFrame's first-write barrier (KARTFRAME_FIRST_WRITE_BARRIER)
A frame whose only layer would be the projection gets a 16x16 transparent quad
(alpha blended, 1 cm, 2 m ahead) after it; its images are cleared once by the
bridge's own command buffer, waited for and released. Before each set's first
writes the bridge submits a barrier ALL_COMMANDS/MEMORY_WRITE to
ALL_COMMANDS/MEMORY_READ|WRITE on its images (layout kept), on Dawn's queue under
its lock, ahead of Aurora's set. XRF lines carry n=<layers>; xrmock counts the
layer lists by shape and flags quads on never-released swapchains.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:56:56 -04:00
simplysanatoriandClaude Fable 5.1 a75676c0b4 DEV.md: lane P instrumentation
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-14 15:43:27 -04:00
simplysanatoriandClaude Opus 5.5 1c42c4d919 perf/session-h11: the eye-pose checks' results and the eleventh session's launch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:42:01 -04:00
simplysanatoriandClaude Opus 5.5 dac9971ecc Eye pose checks: frustum word, GPU uniform probe, cheap stamp; mock bookkeeping before the wait
The design already snapshots each set's packet once (ProvideStereoFrame copies it under
published_mutex_; every eye path uses that copy). This makes the remaining ways one eye
could differ measurable on the headset too:
- the stamp's fourth pose word: the frustum tangents each eye's fill used; xrmock compares
  them with the layer's submitted fov (and the other eye's);
- a GPU uniform probe (KARTFRAME_FRAME_LOG=1 or KARTFRAME_UNIFORM_PROBE=1): after both eyes,
  each eye's first perspective range is read back from g_uniformBuffer (now CopySrc) and
  compared with the bytes its fill wrote, counted per 10 s;
- the XRP fields ride on the XRS line (one log call per set).
The test stamp is 64x15 pixels, one pixel a bit (was 4x4 cells), and xrmock does its
read-back bookkeeping before xrWaitFrame's sleep instead of after the wake-up it measures
from: with the larger stamp that work alone moved 'ends later than 1 ms' by 2 %.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:35:43 -04:00
simplysanatoriandClaude Opus 5.5 d2c67bab62 Per-eye pose stamp: the packet and eye pose each eye's uniform fill wrote
Both fill sites (the seal's eye pair and prepare_late_stereo_replay) record per eye the
packet (display time, token) and the eye transform written, and count draws filled with
another; the stamp block gains three words (rows 7-12, 256x52), an XRP line per set under
KARTFRAME_FRAME_LOG=1 and a 'VR eye poses' summary every 10 s (always). xrmock decodes the
words and compares each eye with the pose its layer submitted, and left against right.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 14:25:39 -04:00
simplysanatoriandClaude Fable 5.1 f20f221f4f DEV.md: lane O switches
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-14 12:49:01 -04:00
simplysanatoriandClaude Opus 5.5 f5a439af27 H9.md: call sequence, Vulkan hand-over, switches, lane N verdict; session 10 launch files
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:44:37 -04:00
simplysanatoriandClaude Opus 5.5 c003213fd7 End locate through the runtime's dispatch (the replay test links no loader)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:37:43 -04:00