Skip to main content

Module resources

Module resources 

Source
Expand description

Dependency-tracked GPU resource graph.

The graph is the renderer’s single source of truth for the wgpu resources a frame draws with — textures and their views, samplers, buffers and bind groups — and for the virtual nodes that hold no handle at all, which group or stand in for the resources around them. Pipeline objects (shader modules, layouts, pipelines) are not tracked: they are immutable once built, and the render pipelines this crate builds are cached by their variant rather than rebuilt from dependencies. Resources are plain wgpu handles — the graph does not wrap them — but it remembers which resource was built from which, so that derived resources can be rebuilt when their inputs change:

  • ResourceGraph::replace swaps a resource and marks every resource transitively built from it as dirty.
  • Dropping the last ResHandle to a resource makes it collectable.
  • ResourceGraph::maintain collects the resources no id and no dependent holds any more, and rebuilds the resources marked dirty.

Nothing happens at the point of the change: replace only flips dirty flags, and taking or dropping an id only moves a reference count. Both take effect the next time ResourceGraph::maintain runs, which is where a frame calls it exactly once — before the resources are read.

Updates are therefore lazy and precise: uploading new bytes into an existing buffer does not dirty anything, reallocating it does, and only the resources that actually consumed the old handle are affected.

§Rebuilding

A resource that can be rebuilt is inserted with a recipe: insert takes an optional Rebuild closure that produces a fresh handle out of the graph. A recipe reads the resources it was built from back out of the graph by id rather than capturing their handles, so it observes the current state of its inputs — a buffer that was reallocated or an array that was replaced — at the moment it runs.

ResourceGraph::maintain runs the recipes of the dirty nodes in dependency order, so a rebuilt resource is always built from already-rebuilt inputs. A dirty node with no recipe is left dirty: the caller changed something the graph cannot rebuild on its own.

§Typed ids

A ResHandle is typed by the ResourceKind it names, and the kind is the resource itself: ResHandle<wgpu::Buffer> resolves to a buffer, ResHandle<TextureView> to a texture view together with its format, and ResHandle<Virtual> to a node that holds no handle. ResourceGraph::get hands that resource back directly, so no caller matches on which variant a node holds and a texture view cannot be read where a buffer is wanted.

The kind is a compile-time claim rather than runtime state: the graph stores every resource in one Resource enum, and a typed id is an index that remembers what it names. Insertion derives the kind from the resource it is given and replace requires the replacement to have the same kind, so an id never names a resource of another kind. Where the kind is genuinely unknown at compile time — a node’s dependencies, a dirty node — the erased ResHandle<Resource> names it instead.

§Retention

An id names a strong reference to its resource: cloning one takes another reference, dropping one gives it up, and ResourceGraph::maintain collects the resource once its last reference is gone. There is no removal call and no handle that goes stale — a resource lives exactly while some id to it does, and letting go of the last id is all it takes to free it.

A resource built from another holds a reference to it too: recording an edge with add_dependency takes one reference from the dependency on behalf of the dependent, so a dependency counts its dependents among the references that keep it alive. A resource that exists only to feed a consumer therefore lives exactly while some consumer does, and collecting a consumer releases whatever it was the last holder of in the same pass. Declaring the same edge twice records it once, and so counts once.

Insertion is immediate: insert adds the node and returns its id, and add_dependency records an edge. Nothing defers, so there is no insertion state to finish and no failure to report — an edge that would close a cycle is a bug in the caller and panics where it is declared.

A Virtual node commonly serves as an aggregation root for a group of resources: the root is built from every part, so the root is the group’s single lifetime entry point. Dropping the last id to the root releases the parts the root was the last holder of, and ResourceGraph::maintain collects them. A part shared by two roots therefore outlives either one alone.

Re-exports§

use std::sync::Arc; 🔒
use std::sync::Weak; 🔒
use crate::dag::Dag; 🔒
use crate::dag::EdgeError; 🔒
use crate::dag::NodeId; 🔒

Macros§

into_resource 🔒
Implement the erasing conversion into Resource for a kind whose stored variant carries it as its only payload.
stored_kind 🔒
Implement ResourceKind for a kind stored in one Resource variant.

Structs§

Node 🔒
NodeInfo
One resource as ResourceGraph::nodes reports it.
Rebuild
A recipe that builds a resource out of the graph it lives in.
ResHandle
Handle to a resource stored in a ResourceGraph, typed by its kind.
ResId
A resource’s identity as a plain value.
ResourceGraph
A directed acyclic graph of wgpu resources.
ResourceGraphInfo
The shape of a ResourceGraph, as plain data.
ResourceGraphMaintain
What one ResourceGraph::maintain pass changed.
ResourceInfo
One resource slot of a ResourceGraph, as plain data.
ResourceKindCount
How many resources of one kind a ResourceGraph holds.
TextureView
A texture view together with the format it views its texture as.
Virtual
The kind of a virtual node: a graph citizen holding no wgpu handle.

Enums§

Resource
A wgpu resource owned by the graph, or a virtual node standing in for one.

Statics§

VIRTUAL 🔒
The one Virtual value, so its ResourceKind can hand out a borrow.

Traits§

ResourceKind
A kind of resource that can live in a ResourceGraph, and the resource an id of that kind resolves to.
TextureExt
Creating texture views whose format the graph can track.

Type Aliases§

StrongRef 🔒
The strong reference count of one node is the number of ResHandles that name it plus the number of nodes built from it, which is exactly what Arc already counts.
StrongRefs 🔒