Repository navigation
[Rendering] Unify temporal history and eliminate TSR, SSR, GI, and PT instability #135
Description
Activity
SSGI temporal-history checkpoint landed in draft PR #147 at
ad8e7c4.Implemented:
- Capture-only probe-domain temporal evidence:
ssgi-rejection-reason.pngandssgi-temporal-confidence.pngflatten the probe X/Y and 8x8 octahedral-texel volume without modifying the production temporal result. - Raw resolved
ssgi.pngplusssgi.metrics.json, so finite output and indirect-radiance presence are gated before display tonemapping. - Invalid half-float trace/history values are bounded component-wise, force refresh directly assigns current radiance, and degenerate depth-derived normals receive finite fallbacks. Ordinary finite radiance and the existing steady-state EMA are unchanged.
- The normal frame adds no diagnostic pass, texture, bind group, or persistent allocation. Capture telemetry reports
ssgi_diagnostic_persistent_bytes=0, one capture-only pass, exact temporary texture/readback bytes, and resources released after capture.
Deterministic retained-scene GPU evidence after backend warm-up:
- accepted probe texels: 4096 / 4096
- current-radiance texels: 2047
- retained-history texels: 4096
- non-finite resolved pixels: 0
- resolved max luminance: 0.9426
Local validation at this commit:
- native library: 294 passed, 0 failed, 1 ignored
- release golden-render corpus: 38 passed, 0 failed, 2 ignored
- FFI parity: 0 failures, 0 warnings
- WebAssembly release build: passed
- WGSL parsing, frame-graph capture contract, formatting, diff whitespace, and file-size guard: passed
PR CI is running. This advances #135 but does not close it: path-tracing denoiser reason/confidence semantics remain the next representation-compatible temporal scope.
- Capture-only probe-domain temporal evidence:
Path-tracing temporal diagnostics checkpoint landed in draft PR #147 at
1041a06.Implemented for realtime PT/SVGF:
- One capture-only trace-grid compute pass emits
pt-rejection-reason.png,pt-motion.png,pt-reprojected-uv.png, andpt-temporal-confidence.pngsimultaneously. - The pass reads the current/previous production SVGF buffers plus existing depth, velocity, and PT matrices after temporal accumulation. It does not write irradiance, moments, history, or the displayed HDR result.
- Rejection classification mirrors the production bilinear depth test and subpixel footprint-retention path. Confidence exposes variance heat, normalized 32-frame history length, and retained-history contribution.
- Normal frames create no PT diagnostic pipeline, bind group, texture, readback, or GPU pass. Capture resources are released after encoding; telemetry reports zero persistent GPU bytes, exact temporary bytes, one capture pass, and the released state.
- Unit guards pin the duplicated capture logic to the production velocity convention, depth tolerances, footprint tolerance, and EMA floor so future denoiser changes cannot silently stale the diagnostics.
M1 Max / Metal ray-query sequence evidence after a 24-frame orbit:
- accepted-history texels: 10,984 / 16,384
- valid-reprojection texels: 10,989
- accumulated SVGF confidence texels: 10,989
- non-finite HDR pixels: 0
- HDR max luminance: 0.3491
Validation at this commit:
- native library: 295 passed, 0 failed, 1 ignored
- release golden-render corpus: 39 passed, 0 failed, 2 ignored
- existing progressive and realtime PT image goldens remained exact on this adapter
- native and wasm32 checks passed
- FFI parity: 0 failures, 0 warnings
- formatting, whitespace, file-size ratchet, and WGSL parse checks passed
This completes the representation-compatible PT reason/confidence extraction planned in the previous checkpoint. #135 remains open for PT-specific moving-object, lighting-change, reset, and required-runner sequence coverage, plus the shared acceleration-ownership finding recorded on #138.
- One capture-only trace-grid compute pass emits
Follow-up to the PT diagnostic checkpoint:
751be72removes its discovered SSGI ownership dependency. Realtime PT now passes the same temporal/HDR gate with SSGI explicitly off, while the PT-only frame plan schedules only shared TLAS/card capture and excludes all four SSGI-only bake/relight passes. The issue documentation no longer lists PT-on/SSGI-off as remaining #135 work.PT moving-geometry sequence coverage landed in draft PR #147 at
a57ab32.The new hardware gate settles realtime PT for 24 frames at pose A, teleports retained rigid geometry to a visibly distinct pose B, captures the first transition frame's PT diagnostics, and follows 24 recovery frames. It requires real velocity coverage, safe retained overlap, explicit rejection for disoccluded motion, bounded trails, and stable stochastic convergence.
M1 Max / Metal evidence:
- visible old/new pose mean RGB delta: 6.1125
- moving trace texels: 855
- velocity-reprojected retained texels: 45
- explicit disocclusion rejects: 810
- unclassified moving texels: 0
- severe trail duration: 0 frames
- frame-four coherent outliers: 0.0031%
- settled stochastic flicker: 0.2388 RGB levels
The full release golden corpus passes with 40 tests passed and 2 intentional ignores; both established PT goldens remain exact. This removes rigid-object motion from the remaining #135 PT sequence list. Lighting-change and reset image sequences plus required-runner timing/cross-backend evidence remain.
PT lighting-change sequence coverage landed at
136096f.The new hardware gate changes directional intensity from 0.15 to 2.4 and back on a static retained ray-query scene. It requires the realtime sample counter to advance continuously (no history reset), a visible state change, bounded contraction toward a settled same-state reference, no coherent stale region by frame twelve, and stable stochastic output.
M1 Max / Metal evidence:
- dark to bright: mean error 22.0257 -> 5.4873 by frame eight; 0% coherent outliers at frame twelve; stable flicker 1.0140 RGB
- bright to dark: mean error 20.0485 -> 7.7487 by frame eight; 0% coherent outliers at frame twelve; stable flicker 1.7009 RGB
- full release corpus: 41 passed, 0 failed, 2 intentional ignores
This removes PT lighting changes from the remaining #135 sequence scope without changing production shaders or accepted images. PT reset image evidence and required-runner timing/cross-backend qualification remain.
PT reset image coverage landed at
ff95b63.After shared TLAS/card warm-up, the hardware gate records a deterministic one-frame realtime PT seed, accumulates a different camera, then exercises both reset routes:
- explicit common temporal/camera-cut reset
- PT off -> on ownership transition
Both outputs are byte-identical to the fresh seed (
max channel delta = 0), restart at exactly one accumulated sample, and the capture contains zero non-gray reason texels: no prior history survives either epoch boundary. The full release corpus now passes 42 tests with 2 intentional ignores.This completes the locally executable #135 PT diagnostic, rigid-motion, lighting-change, and reset sequence plan. The issue remains open for required cross-backend hardware execution and the #127/#128 qualification dependencies; no local acceptance item is being marked complete in place of those external results.
Temporal-contract and checklist reconciliation checkpoint:
5d5d9a1.The authoritative temporal history contract already defines:
- current-minus-previous NDC velocity in UV-sized units
- texture-space Y inversion (
previous_uv = [current.x - velocity.x, current.y + velocity.y]) - current-jitter cancellation against the previous unjittered projection
- current/previous state requirements for rigid, skinned, cached, procedural, transparent, and PT paths
- independent validity/ping-pong/reset ownership for TAA, SSR, SSGI, exposure, SSAO, and PT
- camera-cut, toggle, resize, render-scale, and ownership-transition rules
- per-system rejection/confidence diagnostics and the approved motion/reset sequence thresholds
This commit extracts the previous-projection jitter construction into one production helper and pins it with known-point tests:
- known current/previous NDC points prove current-minus-previous magnitude and the UV Y flip
- a real perspective matrix plus a known 3D point proves exact zero static velocity after current-jitter reapplication
- the negative control omitting that reapplication produces a measurable false velocity
No shader, render pass, resource, format, or per-frame allocation changed. The helper executes the same two once-per-camera matrix additions that were previously inline.
I also reconciled three already-proven sequence criteria that were stale in the issue body:
- EN-061 dark-interior SSR: the focused Metal run reported 4,096 active texels, zero hot/isolated/non-finite texels, raw/march max luminance
0.5, 4,096 retained-history texels, and a visible smooth-reflection control delta of1.8598. - Reset window: the corpus contains byte-identical fresh-seed camera-cut and PT reset/toggle tests, independent TAA/SSR/SSGI/exposure lifetime tests, plus render-scale and resize fresh-seed comparisons.
- Moving geometry: the passing corpus covers retained rigid/reactive motion, cached skinned motion, alpha-tested card motion with required velocity coverage, physical refraction with required velocity/reactive coverage, and realtime PT rigid motion. The documented severe-trail window is at most four frames.
Exact-commit regression gate:
- 318 unit tests passed, 1 ignored
- negotiated production-device smoke passed
- 49 golden/integration tests passed, including every runnable temporal sequence; 2 hardware-only diagnostics intentionally ignored
- 3 render-target tests passed
- strict clippy, wasm32, FFI parity, quality governance/negative controls, file ratchet, and all canonical examples passed
I left four boxes open deliberately:
- exhaustive audit of every remaining particle/procedural motion producer
- coordinated preset/sharpening/default-softness work with Default
render_scale=0.5+ TAA + no sharpening makes output blurry #56 - PT/full-corpus proof on all required supported hardware backends through [Rendering][P0] Restore deterministic path-tracing goldens and oracle correctness #127/[Quality][P0] Add deterministic reference-scene visual and GPU performance qualification #128
- consolidated before/after timing and memory evidence for every temporal history/mask addition
Immediate-mode motion ownership is implemented and pushed in
80ce85c.What changed:
drawCube,drawSphere,drawCylinder,drawPlane, wire, grid, and ray submissions now pair stable call-order slots with prior world-space vertex positions.- First appearance, kind/count mismatch, an empty intervening frame, and explicit temporal reset all seed
previous = current; unrelated geometry cannot emit inherited velocity. - Prior positions reuse the immediate pipeline's existing unused tangent lane. There is no
Vertex3Dstride change, GPU allocation, bind group, draw, render pass, or upload-volume increase. - Runtime telemetry reports immediate-motion entry count, CPU capacity, zero GPU bytes, and zero added passes.
Qualification:
- moved cube: 7,234 meaningful motion pixels;
- severe trail duration: 0 frames;
- frame-four coherent outliers: 0.7599% (gate: 2%);
- stable flicker: 0.4695 (gate: 2.0);
- three-primitive CPU history capacity: 1,728 bytes;
- steady upload: 23,264 B/frame before and after;
- controlled 3×900-frame full render-submit mean: 2.2396 -> 2.2360 ms (-0.16%); no measurable full-frame regression;
- full quick lane green: 322 unit tests, negotiated-device smoke, 50 golden/integration tests (2 hardware-only diagnostics ignored), 3 render-target tests, strict Clippy, wasm, FFI/schema parity, quality governance, and example inventory.
Evidence:
docs/evidence/issue-135-immediate-motion.mddocs/evidence/issue-135-immediate-motion.json
I am leaving “all motion-producing paths” unchecked: retained rigid/skinned/alpha/refraction and immediate primitives are now covered, but particle/custom-translucency ownership is the next unresolved producer class.
Particle/custom-translucency motion checkpoint is implemented and qualified in PR #147.
Commits:
- 8724f30 Add authored reactive coverage for particles
- a0a1765 Record custom particle temporal evidence
- 6921e41 Keep reactive material detection web portable
What changed:
- Custom additive/transparent materials may optionally author
@fragment fn fs_reactive(...) -> ReactiveTranslucentOutalongside the unchangedfs_mainentry. - Coverage is authored 0..1 and unioned into the existing lazy R8 TAA reactive target.
- Only a submitted opt-in material activates the topology and its lazy sibling pipeline. Ordinary custom translucency retains the original single-attachment route and performs no material scan when TAA/feature selection can short-circuit.
- Malformed return contracts fail during material compilation on native and web without shipping a WGSL parser in the browser build.
Motion evidence (Apple M1 Max / Metal):
- 2,222 reactive-rejection pixels
- movement mean 5.5887
- severe trail duration 0 frames
- frame-four outliers 1.0361% (gate: <=2%)
- stable flicker 0.4743 (gate: <=2.0)
- ordinary non-reactive control also has 0 severe trail frames and keeps reactive topology inactive
Cost evidence:
- ordinary frames: 0 added image bytes, passes, draws, uploads, or pipelines
- active opt-in frames: one R8 byte/render-pixel and one lazy sibling pipeline; 0 added passes/draws
- traced steady uploads: exactly 23,264 B/frame before and after
- four alternating 300-warmup/900-frame 1080p runs found no measurable full-frame regression
The complete local quick lane passes: 322 unit tests + 1 intentional ignore, 51 GPU goldens + 2 adapter-gated ignores, render-target tests, strict clippy, wasm/web, all-platform FFI parity, file-size ratchet, quality governance, and example inventory.
Evidence:
docs/evidence/issue-135-custom-reactive-particles.{md,json}.I am leaving the broad all-motion-producers checkbox open until the remaining legacy non-cached skinned path and decal/procedural opt-out audit are closed.
Remaining motion-producer audit is complete in PR #147.
Commits:
38a4403restores previous-palette velocity in the legacy non-cached skin shader.7ec489dqualifies foliage wind plus decal/cloud opt-out behavior.53ce363adds gap-aware unkeyed skin history and gap-aware keyed palette identity.30a3493records the consolidated evidence and contract.
Visual evidence (Apple M1 Max / Metal):
- legacy skin: 10,214 meaningful motion pixels, 0 severe trail frames, 0.8713% frame-four outliers
- unkeyed editor skin: 10,214 meaningful motion pixels, 0 severe trail frames, 0.8636% frame-four outliers
- unkeyed reappearance after a skipped frame: 0 stale-motion pixels
- procedural foliage wind: 7,348 meaningful prior-deformation pixels
- static decal spawn/expiry: 0 severe trail frames, 0.6393% / 0.5157% frame-four outliers
- procedural cloud field change: 0 severe trail frames, 1.1368% frame-four outliers
Cost evidence:
- four alternating 300-warmup/900-frame 1080p runs: median full-frame mean 2.2421 -> 2.2273 ms (-0.66%); every paired mean was lower after
- traced uploads: exactly 23,264 B/frame before and after
- ordinary scene: 0 added GPU bytes, passes, draws, or upload bytes
- active two-joint unkeyed history: 448 measured CPU-capacity bytes, 0 GPU bytes, 0 passes
- legacy skin reuses the existing previous-joint buffer/binding/upload; only weighted-vertex ALU changes
Full local quick lane passes: 322 unit tests + 1 intentional ignore, negotiated-device smoke, 56 runnable GPU goldens + 2 adapter-gated ignores, 3 render-target tests, strict clippy, wasm/web, all-platform FFI parity, file ratchet, quality governance, and all 20 canonical examples.
Evidence:
docs/evidence/issue-135-motion-producer-audit.{md,json}. The broad motion-producer acceptance checkbox is now checked. Preset softness (#56) and required cross-backend full-quality/PT proof remain open.The coherent quality-preset/default-softness criterion is complete via #56 and draft PR #147 (
9c1ab1bthrough29abf80), so I checked that acceptance item.Presets now jointly select resolution, TAA, upscale filtering, composite sharpening, and effect policy; Medium defaults to 0.75, Ultra is native 1.0, and TAA toggles no longer mutate resolution. The production-chain visual gate measures +31.9% resolved detail and 34.6% lower mean difference to native versus the former 0.50 default. A matched old/new 0.50 workload shows no measurable regression, identical upload volume, and zero added persistent resources, history, or passes. Full quick qualification is green without changing goldens or thresholds.
Evidence: issue-56-quality-presets.md.
#135 remains open for the required supported-backend PT/full-quality run and consolidated temporal resource/timing acceptance items.
The consolidated temporal timing/memory criterion is complete in PR #147 at
fa01a92, so I checked that acceptance item.Production ledger:
- SSR, SSGI, TAA, exposure, and PT lifetime fixes reuse their existing histories and add zero production passes.
- SSGI cached diffuse data adds 16 B/probe (32,640 B at native 1080p), no pass, and removes one resolve history lookup per sample.
- measured CPU motion histories: cached model 576 B for one live instance, immediate primitives 1,728 B for three submissions, unkeyed two-joint skin 448 B; all add zero GPU bytes/passes/draws.
- reactive coverage is lazy R8: 1,166,400 B at the shipped Medium default, 2,073,600 B at native Ultra, and 0 B when inactive. It is a second attachment on the existing translucent pass, not another pass.
A new qualification-only retained-transparency workload measures the mask while genuinely active. Four paired 300-warmup/900-frame default-Medium runs reported:
- median full-frame mean 2.3292 ms off -> 2.2716 ms active
- P50 2.4405 -> 2.4556 ms (+0.0150 ms / +0.62%, below scheduling noise)
- P95 3.5403 -> 3.0651 ms
- graph passes 15 -> 15
A dedicated Ultra timestamp run likewise found no localized pass regression (
translucent_pass1.6158 -> 1.4295 ms;taa_pass1.9063 -> 1.8727 ms); lower active values are not claimed as an optimization because Metal timestamp noise is material. All TAA/SSR/SSGI/PT diagnostic masks are separately itemized with exact temporary texture/readback bytes, one capture-only pass each, zero persistent bytes, and released lifetime.The full quick lane remains green: 325 unit tests + 1 intentional ignore, 57 runnable GPU goldens + 2 intentional ignores, 4 render-target tests, FFI/web/Wasm, strict lint/format, governance, visual-fault controls, and examples.
Evidence: issue-135-temporal-cost-ledger.md and its JSON companion.
The only unchecked #135 acceptance item now is the PT/full quality corpus on every required supported backend, tracked by #127/#128 and blocked on the external DX12/Vulkan hardware runner rather than local implementation.
Implemented and pushed SSGI motion stability checkpoint in 8a541b3 (draft PR #147).
Observed Bistro failure and root cause:
- screen probes are 16x16 tiles over the half-resolution buffer (one probe per 32 output pixels at the 0.75 profile);
- placement previously moved by up to +/-4 half-resolution pixels every frame;
- the temporal EMA remained attached to the same probe-grid slot without proving that the new placement still described the prior world-space surface;
- that accumulated unrelated depth layers/surfaces and appeared as gray smoke-like swimming during camera motion.
Fix:
- bound placement dither to +/-0.5 half-resolution pixel;
- retain previous world position and normal in each probe header;
- accept temporal history only when both probes are valid, normal dot is at least 0.85, and world-space displacement is within the depth-scaled continuity bound;
- directly seed current radiance on mismatch, avoiding stale-history evaluation;
- expose changed-surface rejection as cyan in the capture-only SSGI rejection diagnostic, distinct from radiance adaptation;
- keep production topology unchanged: no new texture, bind group, dispatch, draw, or graph pass.
Metal verification on Apple M1 Max:
- shader storage ABI test: pass (80-byte header);
- diagnostic WGSL parse test: pass;
- all five SSGI golden tests: pass;
- settled probe corpus: 4,096/4,096 history octels accepted, 0 refreshed;
- rotated camera corpus: 4,096/4,096 octels rejected as changed surfaces;
- Hi-Z corpus: finite result, nonzero radiance, 2,043 current and 4,096 retained octels;
- added storage: 32 bytes/probe = 65,280 bytes at native 1920x1080; total header is 80 bytes/probe.
The production Bistro binary compiled and linked successfully. A later automated visible-window capture hit a macOS surface-acquisition loop before rendering frames; it was stopped, and the offscreen Metal corpus above completed normally. Interactive Bistro validation is still required for final closure of the user-visible symptom.
Implemented and pushed moving-camera SSR temporal stability in
579605b(fix(renderer): reject view-stale SSR history).What changed:
- SSR history now carries signed receiver-depth provenance in its existing RGBA16F alpha lane (positive traced hit / negative environment fallback); no additional texture, attachment, or persistent GPU memory.
- Reprojected history is rejected when the previous-frame geometric depth does not match the current receiver reprojected through the previous view-projection.
- View-dependent reflection history now ramps from the established 10% current-frame weight at rest to 85% during camera motion, preventing highlights from lagging behind walls/floors while retaining static denoising convergence.
- Diagnostics now distinguish invalid history, geometric disocclusion, neighborhood clamping, and accepted history, and report the actual post-motion confidence.
Qualification:
- Moving-camera dark-interior SSR corpus: 69 geometric rejections, 4,096 motion-refreshed pixels, 4,072 static accepted-history pixels, 4,089 static high-confidence pixels.
- No non-finite SSR pixels or isolated high-radiance outliers; radiance remains below the existing 8.0 firefly bound.
- Visible SSR negative control remains strong (
reflection_delta=6.6270). - SSR lifecycle/reset test passes.
- Full shared library suite: 416 passed, 0 failed, 1 ignored.
- Uniform ABI locked at 144 bytes.
The full 2,909-placement Bistro has been rebuilt and launched with this exact revision for live navigation verification of the reported camera-locked bright wall patch.
1 remaining item
SSGI Bistro visual-stability checkpoint is verified and pushed in
4665e3d(fix(renderer): stabilize SSGI world-space transport).The persistent camera-following red/bright façade strip was traced to a matrix-layout error in probe placement: Bloom uploaded raw
mat4_invert(current_view_matrix)to WGSL even though WGSL consumes the uploaded matrix with the opposite layout forM * v. That horizontally mirrored reconstructed SSGI probe origins across the camera. At the reported façade, a screen probe reconstructed near(-2.89, 2.95, -9.16)and sampled the distant red awning; the correct independent scene raycast was(4.4862, 4.0240, 2.7426). Transposing the inverse view before upload makes the captured probe reconstruct at approximately(4.39, 4.02, 2.64), matching the raycast within diagnostic quantization.The checkpoint also keeps the integrated SSGI transport work: stable cosine-hemisphere probe rays, world-surface temporal reprojection with bounded history, spatial reconstruction, and low-frequency world-coherent Mesh Card radiance. The normal frame adds no diagnostic resources; capture/provenance tooling remains opt-in.
Verification on 2026-08-22:
- Detailed Bistro scene, 1,176 placements, native 1600x900 windowed run: user camera-motion validation confirms the red strip/camera-following light is gone.
- Automated 1,300-frame exact-pose Bistro run: no red strip.
- Native library: 444 passed, 0 failed, 1 intentional ignore.
- Golden/GPU corpus: 74 passed, 0 failed, 2 intentional ignores.
- SSGI corpus: 3,584 current probes, 3,648 retained-history probes, 0 non-finite pixels, max luminance 0.151540.
- SSGI GPU time: 568.872 us total; spatial reconstruction 39.597 us.
- Native glossy slow pan: mean SSIM 0.991087, minimum SSIM 0.990060, derivative error 0.084115.
- Final Bistro binary SHA-256:
9a9fc49e982b0c541ce0147ee81c28d93e98acb5d44a7b65db3d8a7849f80ae7.
A regression test now pins the CPU-to-WGSL inverse-view upload convention by reconstructing a known world point. This resolves the reported SSGI Bistro artifact; #135 remains open for its broader cross-backend/PT acceptance scope.
Temporal/reactive checkpoint
2fef6c6is pushed and fully qualified. TAA now reprojects one frame of prior reactive coverage and unions it with the current mask, so moving transparency/refraction rejects stale color on both its current and newly exposed footprints.The physical-refraction corpus now reports 17,281 reactive-rejection pixels for an 8,525-pixel moving footprint, versus 8,673 before; severe four-frame matched-phase outliers improved from 0.0076% to 0.0061%, with zero trail frames and effectively unchanged settled flicker. Ordinary native/fractional TAA, slow-pan, and emissive recovery metrics remain at baseline. No production pass, allocation, binding, persistent byte, graph resource, or API was added; two 600-frame ordinary TAA timings were 1920.144 us and 1919.310 us versus the 1922-1923 us baseline.
Full shared/GPU golden suites and repository contracts pass. Detailed evidence is recorded on #149: #149 (comment). This resolves the vacated reactive footprint gap; #135 remains open for broader unified-history and cross-backend acceptance.
Temporal-stability checkpoint pushed in 6c69625, with deterministic Bistro sequence capture added in 44eb079.
The static detailed-Bistro case was repeatedly rejecting settled TAA history because jitter changed low-resolution depth ownership while motion remained zero. The fix retains depth-flipped history only for exact static, zero-divergence, broad-color-compatible pixels. Detailed native Bistro diagnostics reduced depth-disocclusion from 7.1154% to 0.0242% and policy rejection from 7.7430% to 0.0091%, while full confidence rose to 99.8058%.
All active library/shader tests (446) and GPU golden tests (76) pass. No pass, allocation, resource, or texture fetch was added, and alternating GPU timings show no measurable regression.
The umbrella remains open: interactive Bistro validation is still needed, and any remaining whole-frame pulse should next be split between TAA and adaptive exposure using T plus fixed-exposure sequence captures.
SSGI temporal/reconstruction checkpoint
76a8ac3is pushed and visually accepted in detailed Bistro.The production path now uses a finite 16-phase integrated angular ring, geometry-clamped unfiltered history, and energy-consistent empty-footprint reconstruction. The severe delayed red/white projections, moving indirect patches, and visible ground support bands are removed without adding passes, rays, samples, allocations, bindings, or persistent bytes. Full local gates pass: 447 library tests and 77 golden/GPU tests, with only the documented hardware-oracle ignores.
The reviewer accepted the SSGI result (“pretty good - let's call it done for now!”). A much subtler residual flicker remains around high-frequency paving, foliage silhouettes, hard shadow/contact edges, and the scooter. Aligned stills plus existing 32-frame pass isolation attribute most of that residual to native TAA jitter/reconstruction, not SSGI or SSR. That remaining scope stays under #135/#149 and was deliberately not folded into the accepted SSGI commit. Detailed SSGI evidence is recorded on #24.
Follow-up to the SSGI checkpoint note: the isolated native-TAA improvement is now committed and pushed separately as
5e65efc.It reduces complete-cycle static phase shimmer by more than half and cuts >8-level range outliers from 4.186% to 0.0209%, with all 447 library and 77 golden/GPU tests green. The smaller residual remains open because compatible high-frequency jitter phases can still raise the color-disocclusion blend weight. Detailed evidence is on #149.
Two verified temporal follow-ups are now pushed:
f9b81b0extends the qualified settled native-TAA policy to coherent sub-quarter-texel camera reprojection. Native slow-pan mean/min SSIM is0.990844/0.989877, derivative error is0.077052, and all motion/disocclusion/reactive guards remain active.- The remaining deterministic raw detailed-Bistro SSGI endpoint residue is explicitly tracked in [Rendering][SSGI] Eliminate detailed-Bistro raw endpoint camera-path residue #150. It reproduces at pushed baseline
5e65efcand the later candidate (0.991724raw SSIM versus the0.9995gate), while final composition passes (~0.999895SSIM, zero outliers). The threshold and quality policy were not weakened.
The complete quick CI lane, 448 active library tests, and 77 active GPU goldens pass. The issue remains open for #150 and the broader PT/full-corpus acceptance work.
Temporal-stability checkpoint
ab4983eis pushed:fix(renderer): retain compatible settled TAA history.This closes a narrow remaining native-TAA failure mode without weakening history safety: fully confident, coherent pixels no longer lose the existing settled 24-frame window solely because compatible color pressure exceeded 1%. Depth disocclusion, reactive coverage, confidence, reprojection, and temporal rejection still unlock history exactly as before.
Detailed Bistro 32-frame evidence for the 195 affected pixels:
- temporal range 11.010256 -> 9.470085 (~14% lower)
- range > 8 outliers 44.2735% -> 34.3590% (~22.4% lower relative)
- final full-frame SSIM versus the prior policy 0.99990
- no new renderer resources or passes
Gates:
- 448 library tests passed
- 77 GPU golden tests passed
- native slow-pan SSIM 0.990844 mean / 0.989877 minimum
- fast rotation and emissive switching retained zero ghost-trail frames
- ABBA timestamped TAA cost 1.62214 ms baseline vs 1.61738 ms candidate
- complete quick CI passed
Rebuilt Bistro SHA-256:
cb971e678434f031313ace57741029a73a12673f65afa03ae86fde6bf6659e9d.The broader temporal-quality epic remains open; this is a stable, pushed sub-checkpoint. Foreground validation of this newest executable is still pending.
Foreground detailed-Bistro validation of ab4983e is now accepted as “pretty perfect”. The severe SSGI transport artifact remains visually absent and the latest compatible-history policy is a clear improvement.
The final intermittent tail is not being silently folded into that acceptance. It is now independently tracked as #151 with the exact binary hash, scene/settings, a 60-second bright/high-frequency camera path, G/T/R/O owner-isolation controls, capture requirements, explicit non-fixes, and closure criteria. #135 remains the temporal umbrella; #151 is the schedulable displayed-image regression.
Temporal-tail evidence checkpoint 466e874 is pushed and recorded in #151. A matched detailed-Bistro G/T/R/O matrix now attributes the remaining subtle flicker overwhelmingly to final TAA reconstruction (90-96% reduction with TAA off; matched SSGI/SSR/occlusion controls neutral). This separates it from the raw SSGI endpoint residue in #150 and gives the umbrella temporal work a deterministic 32-frame oracle before the next production change.
Bistro displayed-output temporal tail is now closed via #151 at pushed
9dcf49f. Exact owner controls isolated the residual to final TAA; a permanent prior-behavior-failing oracle, full temporal/GPU corpora, frozen performance comparison, and a clean windowed detailed-Bistro foreground pass are recorded there.#135 remains open: #150 still owns raw SSGI endpoint/path dependence, #149 owns fractional UE-class temporal reconstruction, and the unchecked PT motion/backend-wide quality-corpus criterion is not yet satisfied.
Current renderer HEAD has completed fresh detailed-Bistro temporal/SSGI revalidation, recorded and pushed in
b54eba9(qualified renderer6677c28).The exact 1,176-placement owner matrix passes its permanent 25 px <=32 px coherent-event gate. TAA-off removes 94-98% of the remaining deterministic signal, while matched SSGI-off changes range/adjacent metrics by only 4.44%/2.41% and does not change the coherent component. A freshly built 1600x900 Ultra HW-ray-query executable then passed the required bright-area and paving motion sweep; the reviewer reported “looking good all around!”. The former red/bright camera-following projection did not return.
Matched performance is neutral-to-better versus accepted SSGI checkpoint
b92668f: synthetic SSGI median 682.258 -> 662.301 us (-2.93%); fully admitted Bistro probe work 6,371.515 -> 6,266.866 us (-1.64%). Release gates are green: 482 library tests and 79 GPU goldens, zero failures, plus 20/20 profiled runs.Evidence is in
docs/evidence/issue-24-ssgi-foreground-revalidation-v1.{md,json}. This completes the pending foreground validation of the current SSGI fixes. The #135 umbrella remains open for its broader PT motion/backend-wide corpus and the independent UE-class reconstruction scope tracked by #149; this comment does not waive those items.Temporal corpus checkpoint 922aff2 extends cross-producer stability coverage at fractional resolution.
New native-matched gates cover rigid, cached skinned, alpha-tested, refractive/reactive, emissive on/off, and deterministic procedural-foliage animation. Each dynamic object case independently bounds image similarity, motion derivative, and convergence toward a separately reset endpoint; all pass with no retained path-dependent trail. The fixed quality clock also makes procedural temporal replay byte-exact.
Full GPU suite: 86 passed, 3 intentionally ignored. Shared suite: 483 passed, 1 ignored. Evidence: docs/evidence/issue-149-fractional-dynamic-native-match-v1.md and .json.
This is a corpus advancement only. No production temporal shader or resource change, and the issue remains open for broader TSR/SSR/GI/PT unification.
Temporal stability cross-check for checkpoint
26b1893: the accepted moving-detail correction does not change accumulation alpha, history lifetime, rejection, neighborhood bounds, sampling kernels, or temporal render-graph topology.The complete dynamic corpus passes rigid, skinned, alpha-tested, procedural-foliage, refraction/reactive, emissive, native-match, and recovery cases. The full Sponza motion repeat reaches minimum SSIM 0.999996364, while motion-derivative RMSE improves from 0.009808212 to 0.009744127. Release profiling shows no measurable regression.
This records compatibility with the unified-history contract; it does not close the broader instability issue.
Integrated WebGPU SSR-temporal validation fix and regression gate at
45d3300(production checkpointd8d47fa).A production 3D browser run exposed that
depth_gradient = abs(dpdx(...)) + abs(dpdy(...))executed after a fragment-varying off-screen history return. Chrome therefore rejected the SSR temporal shader/pipeline even though the previous flat 2D smoke passed. The same derivative calculation now executes in uniform fragment control flow before the return. This changes no on-screen history math and adds no samples, bindings, resources, passes, or persistent bytes.Protection now includes Naga validation, an explicit derivative/source-order assertion, and a real-Chrome temporal scene with TAA + SSR + software SSGI. Repeated 0.75-to-native motion gates pass (
0.027498781frame RMSE,0.024833870motion-derivative RMSE), the browser reports activehiz-screenfallback, and the full 86-test real-GPU renderer corpus remains green. Alternating base/candidate profiles classify the change as no measurable regression.Evidence:
docs/evidence/issue-149-web-fallback-tsr-v1.mdand.json. The wider temporal-history issue remains open for the remaining platform/scene matrix.Full-corpus status audit at integrated checkpoint
f101159keeps the remaining #135 acceptance item explicitly open.All nine versioned scene captures now execute successfully from a clean exact commit on Apple M1 Max / Metal, emit every required final/intermediate artifact, and report zero steady-state resource churn. However, the audit found that absent baselines previously short-circuited hard performance evaluation. Fix
465c5f5makes those failures independent and fail-closed.The corpus is not yet a supported-backend pass: all nine visual baselines await human approval; PBR high, Sponza, skinned-alpha motion, and weighted transparency expose applicable Metal budget overruns; the Vulkan-assigned cases still lack their qualification runner. No baseline, budget, or noise bound was silently changed.
Evidence:
issue-128-bootstrap-matrix-failclosed-v1.md. Hosted quality governance is green (run 33299848026). PT motion goldens and the ultimately approved full Metal/Vulkan corpus remain the outstanding #135 checkbox.
Parent: #126
Includes engine ticket EN-061 from
docs/tickets.mdRelated: #56
Problem
Temporal effects multiply both quality and failure modes. Bloom uses temporal reconstruction/history in TAA/TSR, SSR, screen-probe GI, denoising, exposure, and realtime path tracing, but these systems do not yet share one authoritative motion/history contract. Observed symptoms include SSR fireflies in dark interiors, specular trails, disocclusion smearing, widened block artifacts after upscale, and soft defaults.
Outcome
A common temporal contract plus a qualification/fix pass that makes still and moving output stable across camera motion, object motion, disocclusion, lighting changes, resolution changes, and feature toggles.
Common temporal contract
Define and document once:
Create debug views for motion, reprojected UV, rejection reason, history length, reactive mask, variance, and clamped history.
Required work
TSR/TAA
Ultrais not silently half-resolution/soft; coordinate with Defaultrender_scale=0.5+ TAA + no sharpening makes output blurry #56.SSR
GI and PT denoisers
Motion corpus
Automate at least:
Compare sequences, not only final frames. Report temporal SSIM/FLIP, flicker/variance, ghost trail duration, rejection ratio, and stable-frame convergence.
Acceptance criteria
Likely files
native/shared/src/renderer/postfx_chain.rs,ssr_pass.rs,ssgi_pass.rs,pt_pass.rs,hiz.rs,drs.rsnative/shared/src/renderer/shaders/src/core/native/shared/tests/golden_render.rsNon-goals
Dependencies