Expand description
Rendergraph implementation that rend3 uses for all render work scheduling.
Start with RenderGraph::new
and add nodes and then
RenderGraph::execute
to run everything.
High Level Overview
The design consists of a series of nodes which have inputs and outputs. These inputs can be render targets, shadow targets, or custom user data. The graph is laid out in order using the inputs/outputs then pruned.
Each node is a pile of arbitrary code that can use various resources within the renderer to do work.
Two submits happen during execute. First, all work that doesn’t interact with the surface is submitted, then the surface is acquired, then all the following work is submitted.
Nodes
Nodes are made with RenderGraphNodeBuilder
. The builder is used to
declare all the dependencies of the node (“outside” the node), then
RenderGraphNodeBuilder::build
is called. This takes a callback that
contains all the code that will run as part of the node (the “inside”).
The arguments given to this callback give you all the data you need to do
your work, including turning handles-to-dependencies into actual concrete
resources. See the documentation for RenderGraphNodeBuilder::build
for a
description of the arguments you are provided.
Renderpasses/Encoders
The graph will automatically deduplicate renderpasses, such that if there are two nodes in a row that have a compatible renderpass, they will use the same renderpass. An encoder will not be available if a renderpass is in use. This is intentional as there should be as few renderpasses as possible, so you should separate the code that needs a raw encoder from the code that is using a renderpass.
Because renderpasses carry with them a lifetime that can cause problems, two facilities are available.
First is the PassthroughDataContainer
which
allows you to take lifetimes of length 'node
and turn them into lifetimes
of length 'rpass
. This is commonly used to bring in any state from the
outside.
Second is the RpassTemporaryPool
. If, inside the node, you need to
create a temporary, you can put that temporary on the pool, and it will
automatically have lifetime 'rpass
. The temporary is destroyed right after
the renderpass is.
Structs
Handle to arbitrary graph-stored data.
Wraps a handle proving you have declared it as a dependency.
Container which promotes data from &’node outside a node to &’rpass inside a node.
Reference to data that is passed through.
Mutable reference to data that is passed through.
Output of calling ready on various managers.
Implementation of a rendergraph. See module docs for details.
Provides read-only access to the renderer and access to graph resources.
Holds either a renderpass or an encoder.
Builder for a graph node.
Depth target in a renderpass.
Handle to a declared renderpass output.
Color target in a renderpass.
Targets that make up a renderpass.
Description of a single render target.
Handle to a graph-stored render target.
Pool which extends the lifetime of objects to the length of the renderpass.
Handle to the entire shadow atlas.
Requirements to render to a particular shadow map.
Handle to a single shadow map.
Enums
Handle to something that can be used as depth.