Gfx-rs nuts and bolts

Gfx-rs is a low-level graphics abstraction layer in Rust. This blog supposedly hosts the major milestones, concepts, and recaps of the project.


Release of v0.6

18 Aug 2020

gfx-rs community’s goal is to make graphics programming in Rust easy, fast, and reliable. It governs a wide range of projects:

  • gfx-rs makes low-level GPU programming portable with low overhead. It’s a single Vulkan-like Rust API with multiple backends that implement it: Direct3D 12/11, Metal, Vulkan, and even OpenGL.
  • gfx-extras provides ready-to-use allocators for memory and descriptors in gfx-rs.
  • wgpu-rs is built on top of gfx-rs and gfx-extras. It provides safety, accessibility, and even stronger portability of applications.
  • metal-rs and d3d12-rs wrap native graphics APIs on macOS and Windows 10 in Rust.

Today, we are happy to announce the release of 0.6 versions across gfx/wgpu projects!

gfx-hal-0.6

On gfx-rs project side, the biggest change is converting the incoming lists to be ExactSizeIterator-bound. That allows our backends to stack-allocate any derived data, lowering the overhead.

Other changes are split between incremental improvements, like unbound ranges for mipmap levels and array layers, and totally experimental features, like the mesh shaders.

In the backend space, Vulkan now uses stack allocation everywhere, and D3D12 has seen a number of critical correctness fixes. Hopefully, the latter will get more use and testing in this release, as it’s approaching maturity. At the same time, we had to temporarily disable OpenGL backend, as it’s going through migration to surfman, and it’s not clear now what the future is for this library, given the latest devastating news about Mozilla.

In gfx-memory (of extras), the API is brought closer to gfx-hal, and heuristics are improved, especially for the outlier cases. We are now fuzzy-testing both memory and descriptor allocators.

wgpu-0.6

vangers wgpu shadows

wgpu is rapidly maturing and growing the ecosystem around it. In wgpu-rs on the Web we listed many projects taking advantage of wgpu. During the past 4 months this list more than doubled, and we couldn’t contain all the best parts in the README, so we moved it to a wiki page. We are also featuring a show case on wgpu.rs with some of the interesting projects.

Most important changes in wgpu were about us trying to figure out the proper components, targets, and the API boundaries between them. We ended up with wgpu-core crate having a safe pure-Rust internal API, implementing WebGPU specification. Everything else is built on top of it:

  • wgpu-rs - the idiomatic Rust wrapper
  • wgpu-native - the C API wrapper, aiming to bbe compatible with Dawn
  • Gecko and Servo - for implementing WebGPU API in the browsers

The path to this model was hard and full of unexpected turns. We experienced the bovine invasion, with Cows taking a stronghold inside wgpu repository. We’ve gone through non-exhaustive structs with builders, and then back to plain structs. The best part about it was the unprecedented initiative by our contributors, who weren’t afraid to do large changes, experiment, and scrap intermediate results. Thank you all for surviving this!

In infrastructure, we got an ability to record API traces, replay them on a different machine, and run data-driven tests. Read more on kvark’s blog about this feature! It allows us to easily share workloads that exhibit issues, and fix them promptly, improving the experience for users and developers alike.

On the API side, the most notable additions are write_buffer and write_texture, which allow users to update their GPU data without intermediate staging buffers or encoders. We’ve also got the staging belt implemented for those seeking more control.

We now support a number of powerful native-only extensions, such as descriptor indexing, as well as web-compatible extensions like depth-clamping. Targeting the web is supported, but it’s not useful for the published crate, because the WebGPU API is still evolving and so does browser support for it. Therefore, we recommend anyone who wants to test the Web to stick to the gecko branch.

Finally, the work is ongoing to validate all the use of the API and make it truly safe and portable. Most of the remaining work is related to the shader interface matching, as well as securing the resource accesses from shaders. This largely depends on the progress in next section.

naga-0.2

Naga is our emerging pure-Rust shader infrastructure to convert anything to anything, as well as transform the code in the middle. It aims to be fast and robust, also compiling for WASM target to be used on the Web. It was previously announced as Javelin project but now restarted. We are no longer basing it on rspirv, and the name had to change because it appeared to be reseved on crates.

Naga has modular structure that consists of:

  • front-ends (like WGSL or SPIR-V)
  • intermediate representation (similar to WGSL AST)
  • backends (SPIR-V, HLSL, MSL, etc)

There are many scenarios which Naga wants to help with. One goal is to be able to load SPIR-V or WGSL and reflect it, exposing the shader requirements and the interface to wgpu for validation. Another goal is to parse WGSL, insert bound checks, and produce SPIR-V - this would allow wgpu to accept WGSL like a proper WebGPU implementation, and then feed the SPIR-V output into gfx-rs as usual.

We also want it to parse GLSL and generate SPIR-V, thus replacing the disaster of glsl-to-spirv converters that the Rust ecosystem has been suffering from. Although in the longer run we expect more people choosing WGSL instead of GLSL for their projects.

Finally, but perhaps most importantly, Naga needs to be able to generate the platform-dependent code for all target platforms. This will essentially allow it to replace SPIRV-Cross in gfx-rs, removing this big and problematic native dependency, making our shader translation faster and more robust, and opening the doors to innovation on this front.

We released version 0.2, but this is still heavily a work-in-progress. We invite people interested in graphics and compiler design - collaborating on Naga should be easy given the modular structure, and honestly a joy to develop with the power of Rust ;)