Skip to content

The live passes' buffers by what they hold, and live.rs in files (ROADMAP § 1a) - #65

Merged
yujiaxu-ops merged 2 commits into
mainfrom
live-layout
Nov 13, 2026
Merged

yujiaxu-ops merged 2 commits into
mainfrom
live-layout

Conversation

@yujiaxu-ops

@yujiaxu-ops yujiaxu-ops commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Step 3 of the consolidation agreed after #60: the live passes' data layout, and renderer/src/live.rs split into files. One PR, two commits; neither changes a picture (tier R1).

1. The buffers by what they hold (e4718cd). The state had grown by reuse: a pair named alb held the diffuse fast mean, the upscaler's flicker and lock, and judge's findings over one another; the output colour history sat behind the traced grid's diffuse history in one buffer; velocity had a ping-pong partner nothing read; the g-buffer was allocated at twice what it holds; every pair was swapped by binding the other of two bind groups. Now each lasting state has a buffer of its own, named for what it holds, in two halves (this frame's and the last, chosen by LiveParams.state): diffuse_hist, diffuse_mom, diffuse_fast, spec_hist, gbuffer, up_state, color_hist. The transients that share a buffer are listed at the top of live.wgsl with who uses each when. up_state has half of z and all of w free: the lock's depth (the next fix, for lamps missed in motion) goes there.

  • Storage bindings 28 → 24, one bind group, 16 bytes a pixel less (59 MB at 1440p). Merged layout: 21 live buffers.
  • Live passes 6.27 → 6.13 ms (Bistro, 1440p at 0.375).

2. live.rs in files (8c3ae2a). 4,931 lines → live/mod.rs (LiveCore, settings, camera, governor, readbacks), targets.rs (pipelines, buffers, bind group), load.rs (a scene loaded, the sky's and emitters' workers), edits.rs (edits in place), frame.rs (one frame), session.rs (the headless runner, native only). The items moved as they were, made visible to the parent where it uses them. Every reference to live.rs in comments, docs and tests points at the file the item is in now (one-line edits in world.rs, scene.rs, gpu.rs, docs/VOXEL.md, docs/RUNTIME.md and others).

Checks

result
render-identity, buffers vs main, native nothing changed (after confirm runs: grow-live a flake, three tests within their spread)
render-identity, buffers vs main, THREERT_MERGED=1 nothing changed (physics-instance and shared-pose within their four-run spread)
render-identity, split vs buffers, native 190 outputs: 172 byte-identical, 18 within run-to-run spread, 0 changed
render-identity, split vs buffers, merged 190 outputs: 175 byte-identical, 15 within spread, 0 changed
bench-window still-bistro, tokyo-turn radiance cache on: as close to main as main is to itself (0.03–0.05 ΔE between frames). Cache off: 0.03 against main's 0.01 to itself. A shader compiled from other source rounds differently
cargo test (renderer) 124 passed, 6 ignored
wasm32 library, web crate, npm typecheck / test build; 159 passed

render-identity changes too. It confirms what it flags with four more runs a side, alone (two runs a side under-read a few tests' spread). A confirming run that leaves no output is now left out and counted instead of aborting the gate. geometry/grow-live's frame script adds 1,100 objects and sometimes runs past the script's time limit, so no picture is written. This happens on either build.

ROADMAP § 1a records the step.

🤖 Generated with Claude Code


Note

Medium Risk
Touches the live denoise/upscale shader bindings and buffer sizing used every frame; mitigated by render-identity checks, but merged-layout and FP rounding can still differ slightly from main when the cache is off.

Overview
Reorganizes live post-process GPU state so each temporal quantity has its own storage buffer (diffuse_hist, diffuse_mom, diffuse_fast, spec_hist, gbuffer, up_state, color_hist, sample_vel, etc.) instead of overloaded ping-pong pairs (hist_in/out, ae_in/out, xhist). Frame-to-frame halves are selected via new LiveParams.state and this_half / last_half in live.wgsl; bind layout drops from 28 → 24 storage bindings and saves ~16 B/pixel at 1440p.

Splits the former renderer/src/live.rs (~4.9k lines) into live/ modules (mod.rs, targets.rs, load.rs, edits.rs, frame.rs, session.rs) with no intended behavior change; docs, comments, and tests now reference the new paths (e.g. live/edits.rs for edit_geometry, live/session.rs for headless live).

ROADMAP notes render-identity parity with main, a small live-pass win (~6.27 → 6.13 ms on Bistro), and tighter render-identity confirmation rules.

Reviewed by Cursor Bugbot for commit 8c3ae2a. Bugbot is set up for automated code reviews on this repo. Configure here.

yujiaxu-ops and others added 2 commits November 13, 2026 22:21
…ch (two halves), the transients in one table

What lasts from one frame to the next has a buffer of its own, named for what it holds, in two halves (this frame's
and the previous frame's, alternated by LiveParams.state instead of by swapping bind groups): diffuse_hist,
diffuse_mom, diffuse_fast, spec_hist, gbuffer, up_state, color_hist. Before: a pair of buffers named alb held the
diffuse fast mean, the upscaler's flicker and lock, and judge's findings over one another; the output colour history
sat behind the traced grid's diffuse history in one buffer; velocity had a ping-pong partner nothing read; the
g-buffer was allocated twice what it holds; the Rust names (alb, direct_hist, spec_a / spec_b) said nothing of the
contents. judge's findings use up_state's previous half (judged_slot), as they used the old partner; the transients
that share a buffer (fa, fb, sb, spec_pp, lumq) are listed in one table at the top of live.wgsl, with who uses each
when. up_state's z has a half free (a lock's depth) and w is free.

Storage bindings 28 to 24; one bind group; 16 bytes a pixel less (59 MB at 1440p). Merged layout: 21 buffers.

Checks: render-identity, native and THREERT_MERGED=1, two runs a side and four on what it flagged: nothing changed.
bench-window (still-bistro, tokyo-turn): within a run's spread with the radiance cache on; with it off 0.03 dE
between frames against main's 0.01 to itself (a shader compiled from other source rounds differently). Live passes
6.27 to 6.13 ms (Bistro, 1440p at 0.375).

render-identity now runs what it flags alone, four more times a side (--confirm), before calling it changed: two runs
a side under-read a few tests' spread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, no code changed

renderer/src/live.rs (4,931 lines) is now a directory: mod.rs keeps LiveCore itself (its settings, camera, resolution
governor, readbacks) and what the others share; targets.rs the live passes' pipelines, screen-size buffers and bind
group; load.rs a scene loaded and the workers of its sky and emitters; edits.rs the world's edits applied in place;
frame.rs one frame (the trace, the live passes, the caches' training, the GPU timing); session.rs the headless runner
(native only). The items moved as they were, made visible to the parent where it uses them; the references to
live.rs in comments, docs and tests point at the file each item is in now.

Checks: render-identity against the layout commit's build, native and THREERT_MERGED=1: nothing changed (190
outputs, 171 / 175 byte-identical, the rest within their run-to-run spread). cargo test, the wasm32 library and the
web crate build, npm typecheck and test.

render-identity: a confirming run that leaves no output is left out and counted, not an abort
(geometry/grow-live's frame script sometimes runs past the script's time and writes no picture, on either build).
ROADMAP § 1a records the step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@yujiaxu-ops
yujiaxu-ops merged commit 8746130 into main Nov 13, 2026
9 checks passed
yujiaxu-ops added a commit that referenced this pull request Nov 13, 2026
…t stale in the docs corrected (#66)

CI's renderer job built the renderer and ran none of its ~130 unit tests, though all but a few need no GPU. It now
runs `cargo test --release --locked` after the build: on the runner, which has no GPU, the seven tests that open a
device say "skipped" and return (checked on a Mac with no adapter: 124 pass, those seven among them). The job is
named for it; no check is required by name.

The cleanup (#63, the reservoirs out) and the buffer layout (#65, 28 -> 24 live storage buffers, one bind group)
left docs/RUNTIME.md describing the kernel's 20 and the live passes' 28 storage buffers, seven group-1 buffers with
the reservoirs, the history's two bind groups; merged.rs and gpu.rs comments had the old counts.

ROADMAP "Known issues": under software traversal 24 tests fail on main now, the 23 recorded and
wind/pivot-sway-live (9.241 for 10; hardware traversal passes it). WORKFLOW.md says software traversal is in no gate.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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