Skip to content

rust-gpu v0.4

Compare
Choose a tag to compare
@oisyn oisyn released this 21 Dec 15:53
· 205 commits to main since this release

image
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 crates.io. 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
        acceleration_structure.trace_ray(
            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
}

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

#[spirv(ray_generation)]
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(
        acceleration_structure,
        ray_origin,
        ray_dir,
        payload,
    );

    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:
    #[spirv(fragment)]
    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

spirv-std

  • Added a const-generic Image type, and Image! macro wrapping it. PR#359.
    #[spirv(fragment)]
    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

spirv-builder

  • 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
  • We now verify the build toolchain with the expected toolchain for rust-gpu, by checking the commit hash of rustc. It needs to match exactly. PR#919. Can be overridden by defining the environment variable RUSTGPU_SKIP_TOOLCHAIN_CHECK. PR#935.
  • You can now customize rustc invocation parameters using the environment variables RUSTGPU_RUSTFLAGS="..." and RUSTGPU_CODEGEN_ARGS="...". See documentation for more information. PR#959

Contributors

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

@8picoz, @andrusha, @anirudh24seven, @BeastLe9enD, @bjorn3, @bnjbvr, @Cactice, @ColeSeverson, @DeanBDean, @DJMcNab, @dvc94ch, @eddyb, @ElectronicRU, @emilk, @evopen, @expenses, @follower, @fu5ha, @hannes-vernooij, @haraldreingruber-dedalus, @hatoo, @Hentropy, @hrydgard, @Jake-Shadle, @Jasper-Bekkers, @khyperia, @MarijnS95, @molikto, @msiglreith, @oisyn, @PrototypeNM1, @RDambrosio016, @repi, @TrueDoctor, @urholaukkarinen, @vladinator1000, @XAMPPRocky