Releases: EmbarkStudios/rust-gpu
Rust-gpu v0.6.1
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
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 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
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.
Contributors
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
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
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 ofregister_attr
support in Rust. You now need thespirv
macro attribute to be globally visible by doing:See also this migration guide for more information. PR#926use spirv_std::spirv;
- 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
-genericImage
type, andImage!
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 Vulkan1.1
). PR#559- Added the ability to query entry-point names. [PR#622](https://github.com/EmbarkStudios/rust-gpu/...
rust-gpu v0.3
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 crates.io 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
.
[build-dependencies]
spirv-builder = { git = "https://github.com/EmbarkStudios/rust-gpu.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!
rustc_codegen_spirv
- The biggest change to
rust-gpu
is the added ability to infer storage class types. This removes the need to call.load/.store
on the storage class types, and allows you to useDeref/DerefMut
to manipulate the inner type directly. This a huge improvementrust-gpu
ergonomics, as well leading to more efficient code being generated with the removal of unneededOpLoad
s andOpStore
s when using large types.use spirv_std::{glam::{Vec4, vec2}, storage_class::{Input, Output}}; #[spirv(fragment)] pub fn main_fs( #[spirv(frag_coord)] in_frag_coord: Input<Vec4>, mut output: Output<Vec4>, ) { // Before let frag_coord = frag_coord.load(); output.store(black_box(vec2(frag_coord.x, frag_coord.y))); // Now *output = black_box(vec2(in_frag_coord.x, in_frag_coord.y)); }
- Initial support for Algebraic Data Type enums (e.g.
Option<T>
) has been added. This support is initially only provided for enums which have all scalar values in each variants (integers, floats, booleans). So for exampleOption<u32>
works, butOption<Struct>
doesn't work at the moment. - You no longer need add
#[allow(unused_attributes)]
in front of#[spirv]
attributes to remove warnings. - You can now provide
const
arguments toasm!
. rustc_codegen_spirv
will now remove differentOpName
s that target the same ID. This should reduce the size of the generated SPIR-V binaries.rustc_codegen_spirv
will now try to deduplicate generatedOpVariable
s. This fixes certain issues with compiling rust-gpu SPIR-V on Android platforms.- You can now set
entry_point_name
in entry point attributes to change the final name of an entry point. E.g.#[spirv(vertex(entry_point_name = "foo_bar"))]
- You can now add the
#[spirv(unroll_loops)]
attribute to functions, which tellsrustc_codegen_spirv
to annotate all loops inside withUnroll
.
spirv-std
- Added a new
arch
module which provides an abstraction some basic SPIR-V instructions as free functions. The first iteration includes two functions.vector_extract_dynamic
(OpVectorExtractDynamic
)vector_insert_dynamic
(OpVectorInsertDynamic
)
- Added
textures::StorageImage2d
which is an image designed be read/written to without aSampler
. - Added the
spirv-std-macros
crate for holding thespirv
proc macro which acts as dummy macro to allow to use thespirv
attribute on CPU code (has no affect on CPU code). - Added the
gpu_only
proc macro, which allows you to mark a function as only runnable on GPU, it will still generate a callable function on the CPU side, but it will cause a panic when called. - Added
discard
anddemote_to_helper_invocation
functions. Which correspond todiscard
in GLSL and HLSL respectively. Derivative
is now implemented forglam::{Vec2, Vec3, Vec3A, Vec4}
.- Added the
SampledImage
type, which is an image already combined with a sampler.
spirv-builder
- You can now build your shaders in
release
mode with--release
or withSpirvBuilder::release
- If you're using
spirv-builder
in your build script, you can add the following to yourCargo.toml
to improve build times.[profile.dev.build-override] opt-level = 3 [profile.release.build-override] opt-level = 3
Contributors
Thank you to all the contributors who helped make this release possible!
rust-gpu v0.2
Created by @bcata6 using rust-gpu
(Rust source) with shaders originally from https://shadertoy.com/
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!
Community
- 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
- We've added a new structurizer, which means that you can now use
match
expressions andcontinue
s! - Added the
#[spirv(flat)]
attribute that matches SPIR-V's "Flat" decorator. - Textures are now supported. You can now use the GPU's image memory to sample and manipulate textures.
- Panicking code is now supported.
- Added support for SPIR-V 1.0.
- You can now use procedural macros, such as the
unroll
crate in your shaders. - We've also made some improvements to error messages about constant pointers.
- Thanks to a community contribution we now also have initial support for compute shaders. Though support is still pretty bare bones for now this is an important start towards supporting different shaders in
rust-gpu
. - Added initial support in Rust and
rust-gpu
for inline SPIR-V with theasm!
nightly feature. You can now write inline SPIR-V in your Rust code (example below). This is an important step towards implementing a lot of functionality around SPIR-V's features, such as the aforementioned new texture support.asm! { "%typeSampledImage = OpTypeSampledImage typeof*{1}", "%image = OpLoad typeof*{1} {1}", "%sampler = OpLoad typeof*{2} {2}", "%coord = OpLoad typeof*{3} {3}", "%sampledImage = OpSampledImage %typeSampledImage %image %sampler", "%result = OpImageSampleImplicitLod typeof*{0} %sampledImage %coord", "OpStore {0} %result", in(reg) &mut result, in(reg) &image, in(reg) &sampler, in(reg) &coord }
spirv-std
- All Storage Classes (e.g.
Input
/Output
) are now defined inspirv_std::storage_class
. - Rust's language items such
rust_eh_personality
andpanic_handler
are now defined inspirv-std
for SPIR-V targets. This reduces the amount of boilerplate code you need in your shader, and helpsspirv-std
feel a bit more likestd
. You can still define your own language items by disabling thelang_items
feature.
Misc
rust-gpu
now has testing support for building on Android. You can now also run the WGPU example on Android devices to test out your shaders.
Contributors
Thank you to all the contributors who helped make this release possible!
Introducing rust-gpu v0.1 🐉
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?
- Leading the project:
- @khyperia - compiler engineer with experience from Microsoft & Mozilla
- @Jasper-Bekkers - rendering engineer with experience from Frostbite & SEED, and head of Traverse Research
- @XAMPPRocky & @arirawr, will be helping to manage the open development of the project.
- @VZout, @repi, @MaikKlein, @h3r2tic, @hrydgard, @emilk, @NiklasNummelin - devs that will try to write all their shaders in Rust!
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):
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
.- This is the same mechanism that rustc_codegen_cranelift and rustc_codegen_gcc use.
- Currently only SPIR-V support is planned, Vulkan's open compiler target
- Possible a future version could suppport DXIL (the target for DirectX) or WGSL (the WebGPU shading language that's bijective with SPIR-V)
- Focus on Vulkan graphics shaders first, then after Vulkan compute shaders
- Cargo and crates.io 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?
- Join us on Discord to discuss and share your ideas on this project
- Check out our Roadmap and Milestones
- Read about the project's scope
- Get started and run our example shader
- See our open issues