Skip to content

rust-gpu v0.8

Compare
Choose a tag to compare
@eddyb eddyb released this 02 Jun 22:16
· 61 commits to main since this release

As we keep following Rust's release cadence, it's time for another release of Rust-GPU!
Our project aimed at making Rust a first class language and ecosystem for GPU programming.
You can read more about why we at Embark started this project in the original announcement.

For Rust-GPU 0.8.0, the Rust nightly version has been updated to nightly-2023-04-15,
so make sure to update your rust-toolchain.toml file when upgrading to Rust-GPU 0.8.0.
This Rust nightly is equivalent (in language and library features) to the stable Rust 1.70.0 version, released this week.

As usual, you can find a complete list of changes in the changelog, but keep reading for the highlights.

The SPIR-🇹 shader IR framework is now mandatory

Our SPIR-🇹 shader IR framework started with the goal of allowing us to work with GPU shaders beyond the limitations of manipulating them in their standard SPIR-V form (which is what Rust-GPU has been doing). Back in Rust-GPU 0.4.0, we introduced it as opt-in (behind a --spirt flag), and in Rust-GPU 0.6.0 it became enabled by default (with a --no-spirt opt-out).

While the role it plays in Rust-GPU is still minimal by default (with some experiments behind flags), almost all our plans for improving Rust-GPU's support for the Rust language (such as the qptr experiment) revolve around relying more and more on it, for every step necessary to map Rust semantics onto GPU shader (SPIR-V) semantics.

With this focus on SPIR-🇹 in mind, and to avoid the maintenance cost of duplicate codepaths and testing (not to mention an eventual feature parity gap), we've decided to remove --no-spirt, making SPIR-🇹 mandatory going forward.

How may users be impacted by the removal of --no-spirt?

The most obvious reason one would've used --no-spirt in previous Rust-GPU versions is to work around bugs or incompatibilities unique to SPIR-🇹, which, while entirely possible, is not something we are aware of being done in practice.
If you do encounter such bugs, please report them as a Rust-GPU GitHub issue (and/or as a SPIR-🇹 issue, if the nature of the bug is unambiguous).

But more commonly, --no-spirt has been used by wgpu users to work around naga issue #1977.
wgpu uses naga internally for shader language (and SPIR-V) support, and Rust-GPU loops may cause it to error with:

Shader validation error: 
  ┌─ :1:1
  │
1 │ 
  │   naga::Function [1]

    Function [1] '' is invalid
    The `break` is used outside of a `loop` or `switch` context

While --no-spirt didn't guarantee naga would behave correctly, it did work in more cases than with SPIR-🇹 enabled.
(this was due to some differences in how structured control-flow is represented - SPIR-V supports both while and do-while loops, but naga only implemented while loops initially, and SPIR-🇹 always emits do-while loops)

That naga bug has since been fixed, and the fix is present in:

  • naga 0.11.1, for users of wgpu 0.15
  • naga 0.12.1, for users of wgpu 0.16
  • future naga versions (starting with 0.13, to be used by future wgpu versions)

If you've been using --no-spirt to work around this naga bug, you should be able to update to one of the above versions by using cargo update -p naga, and you can search for "naga" in Cargo.lock (or cargo tree) to check its version.

Further error reporting improvements

Rust-GPU 0.7.0 improved error reporting in some respects, but there were still limitations in how much detail we could record in SPIR-V to be used for error reporting. We've since started using a custom "extended instruction set" (SPIR-V OpExtInst) to give us additional flexibility.

The main improvement is in replacing the basic standard SPIR-V file:line:col debuginfo (OpLine), with a custom one that supports source location ranges as well (which is normally expected of all Rust diagnostics).
Using the same example as the Rust-GPU 0.7.0 release notes:

old (standard) approach new (custom) approach (0.8.0)
image image

We've also added support to our inliner to generate custom debuginfo, to distinguish inlined callee code, from the surrounding caller code. While most errors are reported before any functions are inlined, all SPIR-🇹 passes currently run after the inliner, and in the future diagnostics could ideally be reported at the very end (to maximize the chances of the underlying issue to be legalized away, instead of being reported as an error to the user).

This is the same example, but with RUSTGPU_CODEGEN_ARGS="--no-early-report-zombies" (which delays some reporting):

without any inliner debuginfo support with inliner debuginfo support (0.8.0)
image image

For the first error, all functions were inlined and "called by" didn't even show up in the diagnostics at all, but now it does. There are still some differences between the two errors, but all the useful information should always be present now.