The Render Graph Architecture

What is it:

A render graph (or frame graph) is a way of defining the rendering pipeline using self-contained nodes in an acyclic directed graph. Each node has a set of input and outputs, which link to other nodes or resources. When executed, the graph is traversed executing each node in turn.

One major advantage is the ability to traverse the graph before run time to collect useful data such as resource state transitions, temporary resource use etc. Also, the modular nature of the nodes allows for easy reuse. This architecture allows an engine to support many different renderer configurations without large amounts of code duplication or an unmanageable number of conditionals statements.

In the simple example below the ellipse represents the frame buffer resource needed by the Debug UI node which is then passed to the output to screen node to be displayed on screen.

Simple Render graph example
Simple Render graph example

Adept engine’s implementation

Adept Engine uses render graph instances to handle the many renderer cases present in modern rendering. Each instance is made up of a graph and several patches which are applied at build time. This allows a small set of render graphs to be defined and patches  used to add support for extra features. For example, only a patch to is needed to add support for ray traced reflections rather than create an entire new graph. This same patch could be applied to a forward renderer or a VR render graph without any changes to the base graph definition. This approach allows the engine to support raytracing, VR and multi-GPU rendering with ease and little to no code duplication.

Flow control

In both VR and Multi-GPU rendering, the same rendering passes are repeated multiple times (possibly with slightly different data). Creating a graph that has two rendering passes would work for VR but would cause lots of duplication for Multi-GPU as a new graph would be needed for each GPU in the system. The solution to these issues is the loop node, for VR this loops round twice changing the eye index used. For Multi-GPU ,the nodes are just looped on each GPU (having already been initialised on the respective GPU). All the logic for splitting the frame up is handled by each node based on the device index.

Advantages to normal rendering:

Scheduling

Adept engine uses a fixed graph, where each node is placed manually in the base graph however a graph could use automatic scheduling with each node just listing its dependencies. This would allow for automatic compute work scheduling etc. Unreal Engine 4 (Epic Games) is implementing this approach with their new Render Dependency Graph (more HERE).

Barriers

As the engine has complete knowledge of all the rendering commands ahead of execution, optimal resource barriers can be used. Each node has a start and end state for all its resources. This helps to simplify placement of resource barriers needed in explicit level APIs (Dx12, Vulkan etc.).

The compute pipeline requires resources to be in a compatible state before being used on compute. Commonly the resource is in a state for graphics which means a graphics pipeline must transition it out of that state. Using an informed barrier system, this is handled with ease as the previous graphics node is aware of that the next work is compute so transitions the resource at the end of its work.

This system also supports split barriers, these define a start and end for a state transition and allow the driver to better optimise the transition (more HERE).

Multi-GPU rendering:

One of the key advantages to the render graph architecture is easy support for multi-GPU rendering.  With the addition of inter-GPU transfer nodes, Multi-GPU support is as simple as adding a new graph.  Using loop nodes supporting N number of GPUs is relatively easy.

Disadvantages:

There is a reasonable amount of work needed to create the core node system and render graphs. Porting an existing engine to this architecture could be a very large task. At runtime, there is a small amount of overhead as the system is more complex than a set of simple function calls that a traditional renderer would have.

Examples: 

References:

Framegraph: Extensible Rendering Architecture in Frostbite: https://www.ea.com/frostbite/news/framegraph-extensible-rendering-architecture-in-frostbite.

UE4 – Render Dependency Graph – https://trello.com/c/TILinpNW

Resources about frame graphs: https://github.com/gfx-rs/gfx/wiki/Frame-graphs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s