You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
Unit-test compiler and allocator with synthetic graphs.
Compile the existing serial order without aliasing; prove exact image parity.
Move transient allocation to the compiled lifetime plan.
Cache plans by FramePlanKey; rebuild only on key/resize changes.
Enable conservative aliasing, one resource class at a time.
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.
Parent: #126
Prior design:
docs/rfc/0001-material-render-graph.mdProblem
Bloom now has a useful pass scheduler in
native/shared/src/renderer/graph.rs, a transient pool inrenderer/transient.rs, and an explicit frame sequence inrenderer/mod.rs. It is not yet a production render graph: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
wgpuobject access during graph declaration.Pass model
FramePlanKey(resolution class, quality tier, toggles, capability tier, PT mode). Do not rebuild for values that only change uniforms.Lifetime and allocation
Backend reality
wgpuperforms 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 beforewgpuvalidation and future multi-queue support is possible.Diagnostics
Migration sequence
FramePlanKey; rebuild only on key/resize changes.Acceptance criteria
wgpu-haldependency is introduced.Likely files
native/shared/src/renderer/graph.rsnative/shared/src/renderer/transient.rsnative/shared/src/renderer/mod.rsnative/shared/src/renderer/*_pass.rsnative/shared/src/profiler.rsVerification
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.