Skip to content

Releases: EmbarkStudios/rust-gpu

Rust-gpu v0.6.1

20 Mar 16:19
Choose a tag to compare

A new minor release containing the fix (#1006) for a bug (#1002) causing incorrect SPIR-V to be generated when issuing a OpReturnValue instruction inside an asm! block of a function that gets inlined.

Affected API functions of spirv-std are:

  • IndexedUnchecked::index_unchecked() for [T] and [T; N]
  • IndexedUnchecked::index_unchecked_mut() for [T] and [T; N]
  • AccelerationStrucutre::from_u64()
  • AccelerationStructure::from_vec()
  • RuntimeArray::index()
  • RuntimeArray::index_mut()

This bug got triggered by a new inlining codepath in rustc's MIR and was introduced somewhere before the release of 0.4.0 and remained undetected until now.

A workaround for previous versions of rust-gpu is to compile your shaders without optimizations in general, e.g. by calling release(false) on your SpirvBuilder object, or by making sure the following environment variable is set as such: RUSTGPU_RUSTFLAGS=-Zmir-opt-level=0

rust-gpu v0.6

15 Mar 14:49
Choose a tag to compare

rust-gpu in bevy
Rust-gpu hot reloading in action using the rust-gpu plugin for Bevy

Hi there, and welcome to 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 this version, the nightly has been updated to nightly-2023-01-21, so make sure to update your rust-toolchain file if you want to switch to version 0.6.0. This nightly includes the Rust language features supported by Rust 1.68 released last week.

Image API

This release also contains the first part of a change to the Image API, namely the removal of return type inference for the texture fetch functions. In a nutshell, because of the return type inference, the Rust compiler had to know the type where you store the result of a texture fetch. For most use cases, this implied that you had to specifically store the result in an explicitly typed variable before being able to do further computations on it, like so:

// You had to do this in 0.5.0 and before:
let s: Vec3 = texture.sample(uv);
let result = s.xy() * coefficients;

// Rather than this (this works starting from 0.6.0):
let result = texture.sample(uv).xy() * coefficients;

By removing the return type inference, the texture fetch functions, such as sample(), always return a concrete glam Vector type (typically a glam::Vec4 for unknown and floating point formats). However, in order to do this, we had to make the API less generic, and therefore remove support for user supplied vector library bindings. This also means that glam has now become a non-optional dependency of spirv-std, and you no longer need to add glam as feature when depending on spirv-std (in fact, you'll need to remove glam if specified as feature).

If you were using your own vector library, then unfortunately this is a breaking change. You'll need to either switch to glam, or manually convert to and from your vector type of choice. We may want to add support for other popular vector libraries in the future.

Code generation

Furthermore, we made the previously experimental shader IR framework SPIR-馃嚬 the default. Extensive testing has not resulted in any issues or performance degradation, and in fact this may improve the generated SPIR-V code of your shader. If you previously already opted in using --spirt in the codegen args, you must remove the flag. On the other hand, if this change is causing you issues, you can opt out by specifying --no-spirt (and please let us know by filing a new issue 馃檹). You can do so in the RUSTGPU_CODEGEN_ARGS environment variable, or using the new extra_arg() function when invoking the SpirvBuilder from code.

Community spotlight

A big shoutout to the developers of Bevy, and @Shfty in particular, for adding support for rust-gpu to Bevy. The above title image shows hot reloading of shaders written in rust-gpu in the engine. Awesome work, and much appreciated for fast prototyping of rust-gpu shaders! 馃殌

rust-gpu v0.5

03 Feb 17:42
Choose a tag to compare

Yes that's right, another rust-gpu release! 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.

As we mentioned in the previous release notes, we intended to do more frequent releases, and more or less in line with new stable Rust releases. That way you can use your beloved new Rust features as soon as possible. As Rust 1.67 was released last week, it's time for a rust-gpu update as well.

Not much has changed as the 0.4 release was only a month ago. The most notable changes are the update to the nightly-2022-12-18 toolchain, which should cover all new features new to Rust 1.67. We also made it compatible with Rust edition 2021, while we required 2018 before. As usual, more information in the changelog.

That said, we have been busy with some exciting stuff behind the scenes, as we're focusing on better SPIR-V generation and quality of life improvements to the spirv-std API that'll hopefully make writing shaders in rust-gpu a bit less cumbersome in some situations.


Thank you to all the contributors who helped make this release possible! 馃帀
@Bobo1239, @eddyb, @oisyn.

Special shoutout to @Bobo1239 for submitting their first contribution 馃コ.

rust-gpu v0.4

21 Dec 15:53
Choose a tag to compare

Screenshot from Embark's Creative Playground, which uses rust-gpu and raytracing.

Hi there! It's been long overdue, but it's finally here: the fourth 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.

With this release, all relevant crates have been published to In fact, this has been the case since 0.4.0-alpha.13, released last August. So you no longer have to refer to our github to pull in rust-gpu, and can instead directly refer to spirv-std and spirv-builder by version! What hasn't changed, though, is that you still need to build your shaders using a specific nightly toolchain of Rust. For rust-gpu 0.4.0, this will be nightly-2022-10-29. We do produce a user friendly error message when the toolchain you're building with does not exactly match the version required for rust-gpu.

It has been a while since we published a proper release, and going forward we'd like to do better. We intend to keep rust-gpu on the same schedule as the stable Rust release, so you can use your favorite new language features as new stable versions of Rust are being released, by just updating your rust-gpu version. As of right now, rust-gpu uses a Rust nightly that is equivalent to Rust 1.66, and you can expect a new release on or around the 26th of January, 2023, when Rust 1.67 is planned to be released.

A lot has changed since v0.3, too much to summarize in these release notes. However, we have started to track our changes in a changelog and have even retroactively listing all changes since the first release 馃檪. We'll try our best to feature some of the hightlights here, but please refer to the changelog for a more detailed accounting.

There is one thing we want to highlight in particular: rust-gpu now supports ray-tracing. Using #[spirv(..)] attributes, you can define entry points for various raytracing events: intersection, any_hit, closest_hit, and miss. The #[spirv(ray_generation)] can be used to define a ray generation shader. We still lack proper examples in our codebase, but for now we can refer you to the spirv_std::ray_tracing documentation. The code example below shows a somewhat stripped down shader that is used to generate the shadows in above screenshot.

Show ray-tracing code example
pub struct ShadowPayload {
    shadowed: u32,

pub fn trace_shadow_ray(
    acceleration_structure: &AccelerationStructure,
    mut ray_desc: RayDesc,
    payload: &mut ShadowPayload,
) -> bool {
    payload.shadowed = 1;

    unsafe {
        // see documentation of `spirv_std::ray_tracing::AccelerationStructure` on what these values mean
            RayFlags::SKIP_CLOSEST_HIT_SHADER, // ray flags
            !0,             // cull mask
            0,              // shader binding table offset
            0,              // shader binding table stride
            0,              // miss index
            origin,         // ray origin
            0.0,            // tmin
            direction,      // ray direction
            f32::MAX,       // tmax
            payload,        // payload

    payload.shadowed != 0

pub fn miss(#[spirv(incoming_ray_payload)] payload: &mut ShadowPayload) {
    payload.shadowed = 0;

pub fn raygen(
    #[spirv(descriptor_set = 0, binding = 0)] output_tex: &Image!(2D, format=rgba16f, sampled=false),
    #[spirv(descriptor_set = 1, binding = 0)] acceleration_structure: &AccelerationStructure,
    #[spirv(ray_payload)] payload: &mut ShadowPayload,
) {
    let ray_origin = /* calculate ray origin */;
    let ray_dir = /* calculate ray dir */;

    let shadowed = trace_shadow_ray(

    unsafe {
        output_tex.write(px, if shadowed { Vec3::ZERO } else { Vec3::ONE });

Language and code generation changes

  • Updated toolchain to nightly-2022-10-29.
  • Changed the way the #[spirv(..)] attribute works, because of the removal of register_attr support in Rust. You now need the spirv macro attribute to be globally visible by doing:
     use spirv_std::spirv;
    See also this migration guide for more information. PR#926
  • Replaced spirv_std::storage_class "named pointer types" with #[spirv(...)] &T entry-point parameters. (PR#443). This means you can now use the following code:
    pub fn main(
        #[spirv(frag_coord)] in_frag_coord: &Vec4,    // instead of: #[spirv(frag_coord)] in_frag_coord: Input<Vec4>,
        output: &mut Vec4,                            // instead of: mut output: Output<Vec4>,
    ) {
      // ...
  • Added basic support for unsized structs (e.g. ending with a [T] field). PR#504
  • Removed the need to manually specify the storage class for Image/Sampler/ImageSampler entry-point parameters. PR#567
  • Added support for constant memory (&'static _ references), within the limits of SPIR-V. PR#586
  • Added #[spirv(subgroup_local_invocation_id)]. PR#848
  • Removed the fn/closure #[spirv(unroll_loops)] attribute. You can use #[spirv(unroll)] on individual code blocks instead. PR#946
  • This release includes an experimental new shader IR framework called SPIR-馃嚬, which will ultimately help us in generating better SPIR-V code. This library is opt-in, see here how to enable it. Again, experimental, use at own risk. PR#940

API changes


  • Added a const-generic Image type, and Image! macro wrapping it. PR#359.
    pub fn main(
        #[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled),
        #[spirv(descriptor_set = 1, binding = 1)] image_array: &Image!(2D, type=f32, arrayed, sampled),
        #[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(cube, type=f32, sampled),
        #[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
        output: &mut f32,
    ) {
        let v2 = glam::Vec2::new(0.0, 1.0);
        let v3 = glam::Vec3A::new(0.0, 0.0, 1.0);
        *output = image.sample_depth_reference(*sampler, v2, 1.0);
        *output += image_array.sample_depth_reference(*sampler, v3, 1.0);
        *output += cubemap.sample_depth_reference(*sampler, v3, 1.0);
  • As you might have noticed from above example, cubemaps are now supported as well. PR#521
  • Float packing/unpacking operations. PR#709
  • Lots of other new APIs
    Image: Image::gather/Image::sample_bias#704, Image::query_*#608, Image::read_subpass#643, Image::sample_by_lod/Image::sample_by_gradient#498, Image::fetch#480
    arch: arch::read_clock_khr#757, arch::{signed,unsigned}_{min,max}#763, arch::*memory_barrier*#769, arch::IndexUnchecked#805, arch::atomic_i_increment#839, arch::atomic#877
    Misc: ByteAddressableBuffer#735, SampledImage::sample_by_lod#755, debug_printf!#768, RayQuery::confirm_intersection#822, is_helper_invocation#612, memory_barrier/control_barrier#519


  • You can now have multiple SPIR-V modules, one per entry point. PR#551
  • SpirvBuilder now supports the ability to set a Rust "target triple" (e.g. "spirv-unknown-vulkan1.1" for Vulkan 1.1). PR#559
  • Added the ability to query entry-point names. [PR#622](

rust-gpu v0.3

04 Mar 16:54
Choose a tag to compare

A high res Sci-Fi helmet by @msiglreith

The Khronos Sci-Fi helmet model. glTF model viewer created by @msiglreith using rust-gpu (Source)

Hello everyone, and welcome to the third 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.

We're still not publishing releases to or distributing artefacts for rust-gpu, but we still wanted to highlight some of the changes that have been happening over the past couple of months. For more information on how to get started with using rust-gpu in your projects, be sure to check out the Rust-GPU Dev Guide! You can always add a git dependency in cargo to access spirv-builder.

spirv-builder = { git = "", branch = "main" }

While not a user facing feature, we are also proud to announce that we've also reached an important internal milestone in rust-gpu. We've now completely rewritten our GLSL shaders in our internal Ark project with Rust thanks to the improvements in this release! 馃帀





Thank you to all the contributors who helped make this release possible! 馃帀

rust-gpu v0.2

04 Dec 16:08
Choose a tag to compare


Created by @bcata6 using rust-gpu (Rust source) with shaders originally from

Hello everyone, and welcome to the second 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.

First of all we'd like to welcome @eddyb, who will be working as a collaborator with the rust-gpu team on the compiler backend, and has already been contributing a lot of improvements to rust-gpu!

We're still not really cutting releases for rust-gpu, but we wanted to highlight some of the changes that have been happening over the past month. For more information on how to get started with using it in your projects, be sure to check out the new Rust-GPU Dev Guide!


  • SHADERed, an IDE designed for building shaders have released a plugin and added support for running rust-gpu in SHADERed lite, their in-browser editor. Now you can to write Rust shaders on the web and in an IDE! Check out their blog post for more details on the new features.

SPIR-V Backend




Thank you to all the contributors who helped make this release possible! 馃帀

Introducing rust-gpu v0.1 馃悏

22 Oct 13:36
Choose a tag to compare

Today, we're releasing a very early version of rust-gpu - a new project to make Rust a first-class language and ecosystem for GPU code!

GPU programming has historically been done with HLSL or GLSL, simple programming languages that have evolved along with rendering APIs over the years. However, as game engines have evolved, these languages have failed to provide mechanisms for dealing with large codebases, and have generally stayed behind the curve compared to other programming languages.

Our hope with this project is that we push the industry forward by bringing Rust, an existing low-level, safe, and high performance language, to the GPU. And with it come some additional great benefits: a package/module system that's one of the industry's best, built in safety against race-conditions or out of bounds memory access, a wide range of libraries and tools to improve programmer workflows, and many others!

If we do this project right, developers could use open-source crates that provide the graphical effects needed to create beautiful experiences. Instead of sharing snippets of code on forum posts, they could simply add the right crates.

Why Embark?

At Embark, we've been building our own new game engine from the ground up in Rust. We have previous experience in-house developing the RLSL prototype, and we have a team of excellent rendering engineers that are familiar with the problems in current shading languages both from games, game engines and other industries. So, we believe we are uniquely positioned to attempt solving this problem.

We want to streamline our own internal development with a single great language, build an open source graphics ecosystem and community, facilitate code-sharing between GPU and CPU, and most importantly: to enable our (future) users, and fellow developers, to more rapidly build great looking and engaging experiences.

Who are we?

But we can't do this alone. That's why we've decided to develop this project in the open,alongside the rest of the Rust and graphics programming communities. Please connect with us if you are interested in collaborating

Current Status

Compiling and running very simple graphics shaders works, and a significant portion of the core library also compiles.

With this we've been able to create some first real shaders in Rust, such as this sky shader written (source):

Sky shader

However, many things aren't implemented yet: for example, loops and switches aren't supported yet!

That means that while being technically usable, this project is far from being production-ready.

Project Scope

The scope of this overall project is quite broad, but is in multiple stages

  • rustc compiler backend to generate SPIR-V, plugging in via -Z codegen-backend.
  • Focus on Vulkan graphics shaders first, then after Vulkan compute shaders
  • Cargo and support to develop and publish SPIR-V crates
  • High-level render graph to take advantage of this, make it easy for users to develop and use rendering effects.

An in-depth exploration of our roadmap and milestones can be found here.

Open Development

We'll have weekly meetings on Discord, with open agendas shared in GitHub issues. RFCs and other discussions will also be handled in GitHub.

Want to get started?