Skip to content

[Rendering][P0] Restore deterministic path-tracing goldens and oracle correctness #127

Description

@proggeramlug

Parent: #126

Problem

Bloom's GPU path tracer is the closest in-engine correctness oracle for BRDF energy, direct/indirect visibility, motion reprojection, and denoising. It cannot serve that role unless its golden tests are deterministic and trusted.

The audit found the two path-tracing goldens in native/shared/tests/golden_render.rs failing on the audited worktree:

  • pt_progressive: large mean error plus broad black/speckled regions;
  • pt_realtime_motion: lower mean error but localized high-error trails/outliers.

The worktree contains renderer changes, so the first task is to reproduce on a clean main checkout before assigning blame. Do not update the goldens to make the test green. First determine whether the baseline, harness, backend, or renderer is wrong.

Outcome

A deterministic GPU path-tracing correctness suite that:

  • passes on every supported ray-query backend within documented backend-specific tolerance;
  • fails loudly on transport, TLAS/BLAS, temporal reprojection, denoiser, or resource-lifetime regressions;
  • emits enough evidence for an agent to diagnose a failure without reproducing locally;
  • can act as a reference for realtime renderer changes.

Implementation contract

1. Reproduce and classify

  1. Run each PT golden separately on clean main, recording commit, OS, adapter, driver, backend, features, and actual diff metrics.
  2. Capture pt_progressive.actual.png and pt_realtime_motion.actual.png plus heatmaps.
  3. Add debug captures for raw radiance, albedo, normal, depth, motion, moments/variance, history length, and denoised output.
  4. Classify the first divergent stage. Do not start by widening tolerances.

2. Make stochastic inputs explicit

  • Put the sample seed, sample index, camera frame index, and jitter sequence under test control.
  • Reset all path-tracing history and resource state at test start.
  • Ensure headless initialization cannot inherit process-global or prior-test state.
  • Document which floating-point/backend differences are expected and why.

3. Fix the first incorrect stage

Likely areas include native/shared/src/renderer/pt_pass.rs, native/shared/src/renderer/shaders/pt.rs, TLAS/BLAS update ordering in renderer/mod.rs, motion matrices, SVGF history validation, and render-graph resource ordering. Fix the earliest provably incorrect stage rather than compensating downstream.

4. Improve the failure artifact

On failure, write an artifact directory containing:

  • expected, actual, absolute-diff, and false-color heatmap PNGs;
  • JSON with mean/max error, outlier percentage, SSIM, adapter/backend, seed, frames/spp, and enabled features;
  • named intermediate buffers when BLOOM_GOLDEN_DIAGNOSTICS=1.

Acceptance criteria

  • golden_pt_progressive and golden_pt_realtime_motion pass three consecutive runs on the same adapter with identical or explicitly bounded metrics.
  • At least one Metal and one DX12 or Vulkan ray-query adapter pass in CI or a documented scheduled hardware runner.
  • Injecting a known reprojection error makes the motion golden fail; injecting a BRDF energy error makes the progressive golden fail.
  • No black regions, block trails, NaN/Inf pixels, or uninitialized-history pixels are present in accepted output.
  • CPU reference renders from tools/bloom-reference are used to sanity-check the static scene's energy and occlusion; any expected model difference is documented.
  • Golden changes, if genuinely required after a correctness fix, are isolated in a second reviewable commit with before/after images and an explanation.
  • Unsupported adapters skip with a structured reason; supported ray-query adapters may not silently skip because DXC or a feature was packaged incorrectly.

Verification

cd native/shared
cargo test --release golden_pt_progressive -- --nocapture
cargo test --release golden_pt_realtime_motion -- --nocapture
cargo test --release golden -- --nocapture

Run the relevant reference scene through tools/bloom-reference and attach the result metadata to the PR.

Non-goals

  • Adding new path-tracing features.
  • Raising tolerances to hide a structural regression.
  • Requiring ray query on baseline adapters.

Dependencies

None. This blocks quality claims in every renderer issue under #126.

Activity

  1. proggeramlug commented on Jul 23, 2026

    @proggeramlug
    ContributorAuthor

    Implementation status (2026-07-23): Metal implementation and qualification complete; DX12/Vulkan hardware qualification still pending.

    What the investigation established:

    • A clean git archive of e498433 reproduced the historical progressive PNG byte-for-byte on Apple M1 Max / Metal, but took 167.10 s for 300 frames. Clean-main realtime still had not completed after five minutes and was terminated. This separates the clean baseline from the newer dirty-worktree image corruption while proving a severe Metal performance defect.
    • On the audited renderer worktree, named captures showed clean pipeline/depth/normal/albedo followed by nearly all-black sun visibility and workgroup holes in raw radiance. The first bad stage was the ray query, before accumulation/history/post.
    • Naga 29.0.1 Metal lowering performs intersector.intersect(...) in rayQueryInitialize, sets ready = true, and its non-modern rayQueryProceed path only reads that flag. The canonical proceed loop can therefore fail to advance/terminate. PT, HW-SSGI, and HW-WSRC now skip that loop on Metal; DX12/Vulkan keep the original proceed loop.
    • A second independent bug inverted PT's primary sun vector relative to the raster shader/public setter. PT and the test scene now use the point-to-sun convention (0.5, 1.0, 0.3) used by the CPU oracle.

    Evidence:

    • qualify_pt_oracle_hardware passed on Apple M1 Max / Metal:
      • three progressive repeats: byte-identical (mean/max/outliers = 0, SSIM = 1.0);
      • three realtime-motion repeats: byte-identical (mean/max/outliers = 0, SSIM = 1.0);
      • BRDF-energy fault failed as intended (mean 4.528 > 4);
      • reprojection/cross-surface-history fault failed as intended (6.0883% outlier pixels > 1%);
      • corrected render wall times across qualification runs: 300-frame progressive 0.851–3.537 s, 48-frame realtime 0.187–0.370 s.
    • Full golden test binary: 10 passed, 0 failed, 2 explicitly ignored hardware diagnostics; both ordinary PT goldens reported exact matches.
    • Shared library: 128 passed, 0 failed, 1 ignored; the new backend/query-guard unit tests also pass.
    • CPU pt-golden reference: 256×256, 256 spp, 8 bounces, seed 0; topology/material tests pass and the rendered visibility, silhouettes, shadow direction, and energy agree with the corrected GPU result.
    • Naga validation succeeds for production PT, HW-SSGI, and HW-WSRC as Metal 2.4 (BLOOM_RAY_QUERY_NEEDS_PROCEED=false) and HLSL SM6.0 (true, with RayQuery.Proceed() retained).
    • Failure artifacts now include expected/actual/diff/heatmap, JSON metadata (adapter/features/seed/frame/spp/timing/metrics), and named intermediate captures. Unsupported adapters emit structured skips; BLOOM_REQUIRE_RAY_QUERY=1 makes a supported-runner skip fatal.

    The two PT goldens were intentionally updated only after the corrected Metal intermediates and independent CPU reference were inspected. The old images encoded sunless transport; the new images add coherent direct light and cast shadows, with no block regions/trails or uninitialized history.

    Remaining acceptance item:

    • There is currently no DX12/Vulkan hardware result. GET /actions/runners reports total_count: 0, and hosted Windows/Linux runners do not expose a non-CPU ray-query adapter. I am leaving this issue open until [CI] Make local, PR, hardware, and release quality gates truthful #140 provisions/runs the required hardware gate rather than presenting static shader validation or a structured skip as hardware coverage.

    Canonical hardware command:

    cd native/shared
    cargo test --release --test golden_render \
      qualify_pt_oracle_hardware -- --ignored --exact --nocapture

    Detailed root-cause and reproduction record: docs/pt/PT-6-7-8-skinned-tlas-motion-oracle.md.

  2. proggeramlug commented on Jul 28, 2026

    @proggeramlug
    ContributorAuthor

    PR #147 now strengthens the PT oracle without changing accepted production images:

    • 1041a06 adds one-shot simultaneous realtime captures for rejection reason, motion, reprojected UV, variance/history length/retention confidence, plus raw HDR metrics. This replaces the need to reset and rerun separate debug modes when identifying the first temporal divergence.
    • The capture pass writes no production PT state and has zero normal-frame GPU resources/passes.
    • Its unit contract is pinned to the production velocity convention, depth/footprint thresholds, and EMA floor.
    • 751be72 makes the oracle valid with SSGI explicitly disabled: PT now independently schedules only TLAS/geometry rebuild and raw card capture, rather than relying on the full SSGI bake chain.

    Current M1 Max / Metal evidence remains exact for both checked-in PT goldens in the full release corpus (mean/max/outliers = 0, SSIM = 1.0). The new 24-frame temporal capture also reports 10,984 accepted-history texels, 10,989 valid/accumulated texels, zero non-finite HDR pixels, and finite nonzero radiance.

    This advances the named-intermediate, resource-ordering, non-finite, and silent-skip portions of #127. It does not satisfy the remaining cross-backend requirement: a DX12 or Vulkan ray-query hardware qualification with the three-repeat and negative-control protocol is still required before closing this P0 issue.

  3. proggeramlug commented on Jul 28, 2026

    @proggeramlug
    ContributorAuthor

    Additional realtime PT oracle coverage landed at a57ab32: retained rigid geometry now moves through the production TLAS, velocity MRT, PT reprojection, depth rejection, and SVGF recovery path in an automated hardware sequence.

    The first transition frame records 855 moving trace texels; 45 overlapping texels retain velocity-reprojected history and all 810 newly exposed/disoccluded texels explicitly reject it. No moving texel is unclassified. The image sequence has zero severe-trail frames and 0.0031% coherent outliers at frame four, while the pose change itself is visibly large (mean RGB delta 6.1125).

    This strengthens #127 beyond camera-only motion without changing the accepted PT golden images. Cross-backend DX12/Vulkan qualification remains outstanding.

  4. proggeramlug commented on Jul 28, 2026

    @proggeramlug
    ContributorAuthor

    PT reset-oracle coverage landed at ff95b63: explicit temporal reset and PT off/on both reproduce the warmed fresh realtime seed byte-for-byte after accumulating a different camera. Each path restarts at one sample, and the simultaneous rejection capture has zero non-seed texels.

    Together with a57ab32 rigid motion and 136096f bidirectional lighting response, the local Metal corpus now covers the principal realtime history failure modes without changing accepted PT goldens. #127 still requires its DX12/Vulkan hardware protocol before closure.

  5. proggeramlug commented on Aug 30, 2026

    @proggeramlug
    ContributorAuthor

    Metal requalification after the current rendering checkpoint is complete and pushed.

    Evidence commit: 531f577
    Evidence: https://github.com/Bloom-Engine/engine/blob/531f5779a013c696ef17b0fbc55c538af6acf388/docs/evidence/issue-127-pt-motion-requalification-v1.md
    Qualified renderer: 09ad0b7

    Canonical one-device hardware oracle:

    • 3/3 progressive runs pass with identical metrics: SSIM 0.998132777, 0.038147% coherent outliers.
    • 3/3 realtime camera-motion runs pass with identical metrics: SSIM 0.999404554, 0.012207% coherent outliers.
    • BRDF-energy fault is rejected (mean 5.299 > 4.0).
    • Reprojection fault is rejected (mean 6.441 > 6.0 and 6.0760% outliers > 1.0%).
    • No golden was updated.

    Focused realtime PT temporal corpus: 4/4 pass.

    • SVGF capture: 10,984 accepted-history texels, 10,989 valid/accumulated reprojections, zero non-finite HDR pixels.
    • Rigid motion: zero trail frames; all 855 moving texels classified (45 retained, 810 explicitly rejected).
    • Camera reset and PT off/on reproduce fresh seeds byte-for-byte.
    • Lighting on/off converges with zero frame-12 coherent outliers.

    This reconfirms Metal camera motion, rigid motion, disocclusion, reset ownership, lighting response, diagnostics, and negative controls on current HEAD. #127 remains open only for the required DX12 or Vulkan ray-query hardware run; hosted runners still cannot supply that GPU evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions