Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Resources & Textures

Render graph resources are GPU textures and buffers that passes read from and write to. Each resource has a ResourceId handle used for all graph operations.

ResourceId

#![allow(unused)]
fn main() {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ResourceId(pub u32);
}

ResourceId is an opaque handle returned when you declare a resource. Pass it to add_pass() slot bindings to connect passes to resources.

Resource Types

TypeDescription
ExternalColorColor texture provided externally each frame (e.g. swapchain)
TransientColorColor texture managed by the graph (allocated, aliased, freed automatically)
ExternalDepthDepth texture provided externally
TransientDepthDepth texture managed by the graph
ExternalBufferGPU buffer provided externally
TransientBufferGPU buffer managed by the graph

External vs Transient

External resources are owned by you. You provide them each frame via set_external_texture(). The graph never creates or destroys them. The swapchain texture is the most common external resource.

Transient resources are owned by the graph. The graph creates GPU textures/buffers as needed, tracks their lifetimes, and can alias them (share memory between resources with non-overlapping lifetimes) to minimize VRAM usage.

Creating Color Textures

Use the fluent builder:

#![allow(unused)]
fn main() {
// Transient - graph manages lifetime and may alias memory
let hdr = graph.add_color_texture("scene_color")
    .format(wgpu::TextureFormat::Rgba16Float)
    .size(1920, 1080)
    .clear_color(wgpu::Color::BLACK)
    .transient();

// External - you provide the texture each frame
let swapchain = graph.add_color_texture("swapchain")
    .format(wgpu::TextureFormat::Bgra8UnormSrgb)
    .external();
}

Builder Methods

MethodDescription
format(TextureFormat)Pixel format (default: Rgba8UnormSrgb)
size(width, height)Texture dimensions
usage(TextureUsages)GPU usage flags
sample_count(u32)MSAA sample count
mip_levels(u32)Mipmap level count
clear_color(Color)Clear color (only for the first pass that writes)
no_store()Don't force store after last write
transient()Finalize as transient (returns ResourceId)
external()Finalize as external (returns ResourceId)

Creating Depth Textures

#![allow(unused)]
fn main() {
let depth = graph.add_depth_texture("depth")
    .size(1920, 1080)
    .format(wgpu::TextureFormat::Depth32Float)
    .clear_depth(0.0)
    .transient();
}

Depth Builder Methods

MethodDescription
format(TextureFormat)Depth format (default: Depth32Float)
size(width, height)Texture dimensions
usage(TextureUsages)GPU usage flags
array_layers(u32)For texture arrays (e.g. shadow cascades)
clear_depth(f32)Clear depth value
no_store()Don't force store
transient() / external()Finalize

Creating Buffers

#![allow(unused)]
fn main() {
let data_buffer = graph.add_buffer("compute_data")
    .size(1024 * 1024)
    .usage(wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST)
    .transient();
}

Resource Templates

For creating multiple similar resources, use templates:

#![allow(unused)]
fn main() {
let template = ResourceTemplate::new(
    wgpu::TextureFormat::Rgba16Float,
    1920,
    1080,
).usage(wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING);

let texture_a = graph.transient_color_from_template("blur_a", &template);
let texture_b = graph.transient_color_from_template("blur_b", &template);
}

Template Methods

MethodDescription
new(format, width, height)Create a template
usage(TextureUsages)Set usage flags
sample_count(u32)MSAA samples
mip_levels(u32)Mipmap levels
array_layers(u32)Texture array layers
cube_map()Configure as cube map (6 layers)
dimension_3d(depth)3D texture

Resource Pools

For batch allocation from a template:

#![allow(unused)]
fn main() {
let mut pool = graph.resource_pool(&template);
let [blur_a, blur_b, blur_c] = [
    pool.transient("blur_a"),
    pool.transient("blur_b"),
    pool.transient("blur_c"),
];
}

Setting External Textures Per-Frame

External textures must be provided each frame before execute():

#![allow(unused)]
fn main() {
// Each frame, provide the swapchain texture
let surface_texture = surface.get_current_texture()?;
let view = surface_texture.texture.create_view(&Default::default());
graph.set_external_texture(swapchain_id, view, width, height);
}

Resizing Transient Textures

When the window resizes:

#![allow(unused)]
fn main() {
graph.resize_transient_resource(&device, depth_id, new_width, new_height)?;
graph.resize_transient_resource(&device, scene_color_id, new_width, new_height)?;
}

This invalidates the aliasing info and triggers reallocation on the next execution.