gfx-rs nuts and bolts

gfx-rs is a project bringing efficient cross-platform graphics to rust. This blog supposedly hosts the major milestones, concepts, and recaps of the project.


The rise of wgpu

06 Mar 2019

gfx-rs is a Rust project aiming to make graphics programming more accessible and portable, focusing on exposing a universal Vulkan-like API targeting all platforms. Over the past 2 years we’ve put a lot of effort into making gfx-rs API compatible with Vulkan and wrapping it in the Vulkan Portability bindings. We optimized the Metal backend, nailed down hundreds of issues revealed by Vulkan Conformance Test Suite, contributed our expertize to the standardization process. What didn’t go entirely smoothly was the integration into Rust ecosystem: building libraries and applications on top of gfx’s hardware abstraction layer (hal) proved to be extremely challenging due to the low-levelness and unsafety of the API. There is a serious demand for an API that has the capabilities of Vulkan but is easier to work with.

The main community driving gfx-hal adoption today is the Amethyst game engine, and they produced a nice helper library called Rendy. As they call it, a “collection of crates to build your own renderer”. The concept is reminiscent of LLVM (“build your own compiler”) and overall fits nicely into the Amethyst philosophy. The project has recently been released, and is worth checking out despite being experimental. Amethyst hasn’t fully switched to gfx-hal yet, Rendy is version 0.1.1, and gfx’s mileage may vary per backend. We’re having a lot of fun with it already, but that’s not all.

WebGPU

WebGPU is a new graphics/compute API developed by the browser vendors (and Intel) within W3C:

The goal is to design a new Web API that exposes these modern technologies in a performant, powerful and safe manner.

Don’t be confused by the “Web” part here - both us (gfx-rs team) and Google are trying to make it feasible to run on native platforms as well. Typically, the Web as a platform has different priorities from native: a lot of focus is placed on the security and portability (in a wider and stronger sense). Coincidentally, these are qualities we are currently missing in the gfx-rs ecosystem: security means safety (in the Rust sense), and portability means that people can use it and run everywhere, without worrying about thousands of potential configurations at run-time, or diverging behavior between platforms due to timing differences or loosely defined behavior.

With these goals in mind, we’d like to announce our new project: wgpu-rs.

wgpu-rs

wgpu-rs is aiming to be a safe, portable API which reduces the complexity of working with low-level graphics APIs. It has a layered implementation:

  • The wgpu-native layer which exposes a C API. wgpu-native is implemented on top of gfx-hal which allows it to work with the same platforms that gfx-hal already supports. The idea is that wgpu-native will have a compatible C API with Google’s Dawn implementation so they can be used interchangeably for applications compiled in other languages.
  • The wgpu-rs layer which is an idiomatic safe Rust API. It uses wgpu-native internally on native targets. It will use Web APIs (from WASM host bindings) directly when targeting the Web in the future.

Let’s dive into the mentioned qualities of the API:

Simple

Writing straight Vulkan code for an application can easily challenge a user’s sanity. It’s a great API, it’s well documented, but still very complex, and it’s made with a focus on engines as opposed to direct users. You have to think about the memory allocations, pipeline stages, resource states and lifetimes, all the time. Just rendering a textured rectangle out there without triggering any validation warnings is an achievement.

WebGPU automates some of the aspects of low-level graphics APIs which have high complexity but low return on investment. It still has the core pieces of the next-gen APIs, such as command buffers, render passes, pipeline states and layouts. Because the complexity is reduced, users will be able to direct more focus towards writing efficiently application code.

Safe

WebGPU is designed from the ground up to have all the validation built-in. In our case, wgpu-native is responsible for sanitizing the inputs, capturing invalid usages, and reporting back to the user. This means that our wgpu-rs wrapper can be entirely safe in the Rust sense. We don’t even rely on Rust syntax and features for safety, since it’s handled at the lower level, so we can have as much type-safety as we want to feel comfortable, or as little as needed to be flexible.

Portable

The code runs on a variety of platforms from a single source: Vulkan, Metal, D3D12/D3D11, and eventually the Web (when the browsers gain support for the API, which is also in our scope of work). And it’s expected to behave exactly the same, independent of the exposed hardware queues, image format capabilities, or memory types.

Picking up the flag

In a way, WebGPU is trying to accomplish all the goals we set for ourselves originally at the start of gfx-rs project. And that’s why we are so enthusiastic about it: it’s more modern, it’s more safe, it’s more portable, and there is a working group behind it with strong momentum which will eventually become widespread. Today we are releasing wgpu-0.2 for the community to try out. It’s still largely incomplete (e.g. no validation or error reporting yet), but it reached a point of being usable:

WGPU shadow WGPU asteroid

wgpu-rs is a heavy work in progress, has only been developed since September last year, and as such some assembly is still required. However, those who don’t mind some tinkering, will find a promising library with a bright future and a compelling compatibility proposition already. We are looking forward to see what the community is able to accomplish with it, and I myself (@kvark) have a number of projects using gfx pre-ll that have been waiting for this moment to upgrade. With wgpu-rs we can finally deprecate the old gfx and have a solid recommendation for people getting started with graphics in Rust.