Rafx is a multi-backend rendering framework targeted specifically at games and tools for games. It provides:
rafx-api
)rafx-framework
)distill
asset pipeline (rafx-assets
)rafx-shader-processor
and other toolsWhile there are many crates similar in scope to rafx-api
there are fewer high-level options in the rust ecosystem.
The full stack of Rafx crates aims to be similar in scope to Ogre3D or Horde3D, but modernized and following
industry practices where possible.
Rust already has an amazing selection of low-level rendering crates: wgpu
, vulkano
, glium
, lots of
raw bindings to platform APIs like ash
and metal
, and more. So it’s fair to ask, why make another one?
Rafx intends to support multiple platform APIs, and as of late 2020 when rafx-api
was created, gfx-hal
and wgpu
were the only choices that met this criteria. (As of late 2021, gfx-hal
is deprecated and wgpu
is the only choice
I’m aware of.)
gfx-hal
was deprecated in mid-2021. This issue describes why, and
some of the issues mentioned there were factors in choosing not to use it. It was unsafe API that closely followed the
API design of vulkan. Because it so closely followed vulkan, it had concepts and features that did not map cleanly to
other APIs we want to support. When necessary, gfx-hal
went to great length to hide this, adding complexity.
rafx-api
is also unsafe, but has a reduced API footprint that is more easily supported across modern platform APIs.
This keeps backends simple to read and debug, while hopefully improving ease of use. In some cases, the provided API
will not be sufficient, so rafx-api
fully exposes the underlying platform APIs and resources. This allows full, native
control and access to the very latest features in the underlying platform API.
wgpu
is a fully safe API that closely follows the webgpu standard. To ensure safety, GPU resources are tracked at
runtime so that they are not dropped while in use. Additionally, resources are automatically placed in the correct
state for the GPU to use them. This safety combined with a less vulkan-centric API design made it much easier to use
than gfx-hal
. It has since become very popular in the rust community.
rafx-api
does not have these safety guarantees (or complexity/overhead required to support them). Instead,
rafx-framework
provides higher-level tools and abstractions that mitigate this unsafety. For example, the render graph
automatically handles placing resources into the correct state. It can potentially do this in a more optimal way because
it has a holistic view of what will happen during the entire frame.
In mid-2020, wgpu
was relicensed from MPL to the less restrictive MIT/Apache-2.0 license. Additionally, the structure
of the project was drastically simplified. In my opinion, these are great changes that make wgpu
an easy
recommendation for many projects. Even so, I think rafx-api
is sufficiently different from wgpu
in engineering
tradeoffs to make it worth considering for certain kinds of projects.
While there are many low-level rendering solutions in Rust, fewer high-level solutions exist.
rafx-framework
provides a rendering framework based on ideas that are in use in modern, shipping AAA games.
rafx-framework
provides reference counted GPU resources, descriptor set management, a render graph, a material
system, and flexible handling for vertex data at runtime.
Additionally, rafx-framework
can use additional metadata extracted by rafx-shader-processor
to implement time-saving
features like automatically binding immutable samplers and
uniform buffers to descriptor sets.
Rafx includes full integration with the distill
asset pipeline. It supports many advanced features such as streaming
assets to remote devices and hot reloading of data.
See Distill
for more info.
Rafx includes a shader processor the pre-cooks shaders for multiple platforms. This avoids needing to do just-in-time shader translation/compilation on end-user devices. This permits many heavy non-rust dependencies to be excluded from the game itself.
Additionally, the shader processor can generate rust code that provides a type-safe interface for working with descriptor sets compatible with a given shader.