Skip to content

[Renderer] Compile the render graph with lifetime planning, aliasing, and topology caching #129

Description

@proggeramlug

Parent: #126
Prior design: docs/rfc/0001-material-render-graph.md

Problem

Bloom now has a useful pass scheduler in native/shared/src/renderer/graph.rs, a transient pool in renderer/transient.rs, and an explicit frame sequence in renderer/mod.rs. It is not yet a production render graph:

  • topology is constructed during the frame instead of compiled and cached by feature/configuration key;
  • resource versions, first/last use, alias compatibility, and read-before-write validation are not a complete contract;
  • pass ordering is largely a pinned serial predecessor chain;
  • resource usage transitions and queue intent are not represented for diagnostics/future scheduling;
  • graph construction and resource churn contribute to the per-frame allocation tail documented as EN-056.

This makes quality features harder to add safely and encourages hidden pass-order dependencies such as the black-frame bind-group-cache regression described in #30.

Outcome

A compiled render graph that owns transient resource planning, validates every pass's data contract, caches stable topologies, and emits a deterministic execution plan without changing public rendering APIs.

Architecture contract

Resource model

  • Typed logical handles for textures and buffers; no raw wgpu object access during graph declaration.
  • Each write creates a new logical version. Reads name the version they consume.
  • Imports for persistent/external resources (swapchain, histories, atlases) state initial/final usage and ownership.
  • Descriptors include format, dimensions/scale, mip/layer count, samples, usage, clear/load policy, and alias class.

Pass model

  • A pass declares reads, writes, read-writes, side effects, queue capability, and an execution closure.
  • Compilation builds a DAG from resource edges, rejects cycles/read-before-write/double-writer mistakes, and topologically sorts deterministically.
  • Optional passes are selected before compilation by a hashable FramePlanKey (resolution class, quality tier, toggles, capability tier, PT mode). Do not rebuild for values that only change uniforms.

Lifetime and allocation

  • Compute first/last use for every transient resource.
  • Alias only descriptor-compatible resources with non-overlapping lifetimes.
  • Cache physical allocations by compiled plan and resize generation.
  • Persist temporal histories explicitly; never allow them to alias transient resources.

Backend reality

wgpu performs backend barriers, so this issue does not invent a second barrier API. The graph must still validate declared usages and expose transition/queue metadata so incorrect resource contracts are found before wgpu validation and future multi-queue support is possible.

Diagnostics

  • Stable pass/resource names and debug markers.
  • DOT/JSON dump showing dependencies, lifetimes, aliases, and physical allocations.
  • Per-pass CPU/GPU timings connected to the same stable names.
  • Debug capture requests by logical resource name.

Migration sequence

  1. Unit-test compiler and allocator with synthetic graphs.
  2. Compile the existing serial order without aliasing; prove exact image parity.
  3. Move transient allocation to the compiled lifetime plan.
  4. Cache plans by FramePlanKey; rebuild only on key/resize changes.
  5. Enable conservative aliasing, one resource class at a time.
  6. Remove legacy manual ordering/allocation paths after all configurations are represented.

Acceptance criteria

  • Unit tests cover cycles, missing producers, multiple writers, persistent imports, optional passes, alias compatibility, and deterministic sorting.
  • The graph compiles once per stable configuration, not once/twice per frame; a counter/golden test enforces this.
  • All current raster, GI, post-FX, custom material, screenshot, and path-tracing paths execute through the graph.
  • No quality-corpus case changes beyond the approved tolerance during the no-aliasing migration.
  • Conservative aliasing reduces peak transient texture bytes by at least 25% on the Ultra Sponza frame, or the PR documents measured constraints preventing that target.
  • Graph dumps and debug markers make every frame pass/resource inspectable in RenderDoc/Xcode/PIX-compatible captures.
  • Existing unsupported multi-queue behavior remains serial and correct; no direct wgpu-hal dependency is introduced.

Likely files

  • native/shared/src/renderer/graph.rs
  • native/shared/src/renderer/transient.rs
  • native/shared/src/renderer/mod.rs
  • pass modules under native/shared/src/renderer/*_pass.rs
  • native/shared/src/profiler.rs

Verification

cd native/shared
cargo test --release

Run the quality corpus at every quality/capability tier and attach before/after graph dumps, peak transient bytes, and pass timings.

Non-goals

Dependencies

Can start immediately. It should land before virtual shadow maps and before broad visibility-pipeline migration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions