Themes of this release
This release's theme is one that is likely to repeat for a few releases: convergence with the WebGPU specification! WGPU's design and base functionality are actually determined by two specifications: one for WebGPU, and one for the WebGPU Shading Language.
This may not sound exciting, but let us convince you otherwise! All major web browsers have committed to offering WebGPU in their environment. Even JS runtimes like Node and Deno have communities that are very interested in providing WebGPU! WebGPU is slowly eating the world, as it were. 😀 It's really important, then, that WebGPU implementations behave in ways that one would expect across all platforms. For example, if Firefox's WebGPU implementation were to break when running scripts and shaders that worked just fine in Chrome, that would mean sad users for both application authors and browser authors.
WGPU also benefits from standard, portable behavior in the same way as web browsers. Because of this behavior, it's generally fairly easy to port over usage of WebGPU in JavaScript to WGPU. It is also what lets WGPU go full circle: WGPU can be an implementation of WebGPU on native targets, but also it can use other implementations of WebGPU as a backend in JavaScript when compiled to WASM. Therefore, the same dynamic applies: if WGPU's own behavior were significantly different, then WGPU and end users would be sad, sad humans as soon as they discover places where their nice apps are breaking, right?
The answer is: yes, we do have sad, sad humans that really want their WGPU code to work everywhere. As Firefox and others use WGPU to implement WebGPU, the above example of Firefox diverging from standard is, unfortunately, today's reality. It mostly behaves the same as a standards-compliant WebGPU, but it still doesn't in many important ways. Of particular note is Naga, its implementation of the WebGPU Shader Language. Shaders are pretty much a black-and-white point of failure in GPU programming; if they don't compile, then you can't use the rest of the API! And yet, it's extremely easy to run into a case like that from #4400:
fn gimme_a_float() -> f32 {
return 42; // fails in Naga, but standard WGSL happily converts to `f32`
}We intend to continue making visible strides in converging with specifications for WebGPU and WGSL, as this release has. This is, unfortunately, one of the major reasons that WGPU has no plans to work hard at keeping a SemVer-stable interface for the foreseeable future; we have an entire platform of GPU programming functionality we have to catch up with, and SemVer stability is unfortunately in tension with that. So, for now, you're going to keep seeing major releases and breaking changes. Where possible, we'll try to make that painless, but compromises to do so don't always make sense with our limited resources.
This is also the last planned major version release of 2024; the next milestone is set for January 1st, 2025, according to our regular 12-week cadence (offset from the originally planned date of 2024-10-09 for this release 😅). We'll see you next year!
Contributor spotlight: @sagudev
This release, we'd like to spotlight the work of @sagudev, who has made significant contributions to the WGPU ecosystem this release. Among other things, they contributed a particularly notable feature where runtime-known indices are finally allowed for use with const array values. For example, this WGSL shader previously wasn't allowed:
const arr: array<u32, 4> = array(1, 2, 3, 4);
fn what_number_should_i_use(idx: u32) -> u32 {
return arr[idx];
}…but now it works! This is significant because this sort of shader rejection was one of the most impactful issues we are aware of for converging with the WGSL specification. There are more still to go—some of which we expect to even more drastically change how folks author shaders—but we suspect that many more will come in the next few releases, including with @sagudev's help.
We're excited for more of @sagudev's contributions via the Servo community. Oh, did we forget to mention that these contributions were motivated by their work on Servo? That's right, a third well-known JavaScript runtime is now using WGPU to implement its WebGPU implementation. We're excited to support Servo to becoming another fully fledged browsing environment this way.
Major Changes
In addition to the above spotlight, we have the following particularly interesting items to call out for this release:
wgpu-core is no longer generic over wgpu-hal backends
Dynamic dispatch between different backends has been moved from the user facing wgpu crate, to a new dynamic dispatch mechanism inside the backend abstraction layer wgpu-hal.
Whenever targeting more than a single backend (default on Windows & Linux) this leads to faster compile times and smaller binaries! This also solves a long standing issue with cargo doc failing to run for wgpu-core.
Benchmarking indicated that compute pass recording is slower as a consequence, whereas on render passes speed improvements have been observed. However, this effort simplifies many of the internals of the wgpu family of crates which we're hoping to build performance improvements upon in the future.
By @Wumpf in #6069, #6099, #6100.
wgpu's resources no longer have .global_id() getters
wgpu-core's internals no longer use nor need IDs and we are moving towards removing IDs completely. This is a step in that direction.
Current users of .global_id() are encouraged to make use of the PartialEq, Eq, Hash, PartialOrd and Ord traits that have now been implemented for wgpu resources.
set_bind_group now takes an Option for the bind group argument.
https://gpuweb.github.io/gpuweb/#programmable-passes-bind-groups specifies that bindGroup is nullable. This change is the start of implementing this part of the spec. Callers that specify a Some() value should have unchanged behavior. Handling of None values still needs to be implemented by backends.
For convenience, the set_bind_group on compute/render passes & encoders takes impl Into<Option<&BindGroup>>, so most code should still work the same.
By @bradwerth in #6216.
entry_points are now Optional
One of the changes in the WebGPU spec. (from about this time last year 😅) was to allow optional entry points in GPUProgrammableStage. In wgpu, this corresponds to a subset of fields in FragmentState, VertexState, and ComputeState as the entry_point member:
let render_pipeline = device.createRenderPipeline(wgpu::RenderPipelineDescriptor {
module,
entry_point: Some("cs_main"), // This is now `Option`al.
// …
});
let compute_pipeline = device.createComputePipeline(wgpu::ComputePipelineDescriptor {
module,
entry_point: None, // This is now `Option`al.
// …
});When set to None, it's assumed that the shader only has a single entry point associated with the pipeline stage (i.e., @compute, @fragment, or @vertex). If there is not one and only one candidate entry point, then a validation error is returned. To continue the example, we might have written the above API usage with the following shader module:
// We can't use `entry_point: None` for compute pipelines with this module,
// because there are two `@compute` entry points.
@compute
fn cs_main() { /* … */ }
@compute
fn other_cs_main() { /* … */ }
// The following entry points _can_ be inferred from `entry_point: None` in a
// render pipeline, because they're the only `@vertex` and `@fragment` entry
// points:
@vertex
fn vs_main() { /* … */ }
@fragment
fn fs_main() { /* … */ }WGPU's DX12 backend is now based on the windows crate ecosystem, instead of the d3d12 crate
WGPU has retired the d3d12 crate (based on winapi), and now uses the windows crate for interfacing with Windows. For many, this may not be a change that affects day-to-day work. However, for users who need to vet their dependencies, or who may vendor in dependencies, this may be a nontrivial migration.
By @MarijnS95 in #6006.
New Features
Naga
- Support constant evaluation for
firstLeadingBitandfirstTrailingBitnumeric built-ins in WGSL. Front-ends that translate to these built-ins also benefit from constant evaluation. By @ErichDonGubler in #5101. - Add
firstandeithersampling types for@interpolate(flat, …)in WGSL. By @ErichDonGubler in #6181. - Support for more atomic ops in the SPIR-V frontend. By @schell in #5824.
- Support local
constdeclarations in WGSL. By @sagudev in #6156. - Implemented
const_assertin WGSL. By @sagudev in #6198. - Support polyfilling
inversein WGSL. By @chyyran in #6385. - Add base support for parsing
requires,enable, anddiagnosticdirectives. No extensions or diagnostic filters are yet supported, but diagnostics have improved dramatically. By @ErichDonGubler in #6352, #6424, #6437. - Include error chain information as a message and notes in shader compilation messages. By @ErichDonGubler in #6436.
- Unify Naga CLI error output with the format of shader compilation messages. By @ErichDonGubler in #6436.
General
- Add
VideoFrametoExternalImageSourceenum. By @jprochazk in #6170. - Add
wgpu::util::new_instance_with_webgpu_detection&wgpu::util::is_browser_webgpu_supportedto make it easier to support WebGPU & WebGL in the same binary. By @Wumpf in #6371.
Vulkan
- Allow using VK_GOOGLE_display_timing unsafely with the
VULKAN_GOOGLE_DISPLAY_TIMINGfeature. By @DJMcNab in #6149.
Metal
- Implement
atomicCompareExchangeWeak. By @AsherJingkongChen in #6265. - Unless an explicit
CAMetalLayeris provided, surfaces now render to a sublayer. This improves resizing behavior, fixing glitches during on window resize. By @madsmtm in #6107.
Bug Fixes
Naga
- SPIR-V frontend splats depth texture sample and load results. Fixes issue #4551. By @schell in #6384.
- Accept only
vec3(notvecN) for thecrossbuilt-in. By @ErichDonGubler in #6171. - Configure
SourceLanguagewhen enabling debug info in SPV-out. By @kvark in #6256. - Do not consider per-polygon and flat inputs subgroup uniform. By @magcius in #6276.
- Validate all swizzle components are either color (rgba) or dimension (xyzw) in WGSL. By @sagudev in #6187.
- Fix detection of shl overflows to detect arithmetic overflows. By @sagudev in #6186.
- Fix type parameters to vec/mat type constructors to also support aliases. By @sagudev in #6189.
- Accept global
vars without explicit type. By @sagudev in #6199. - Fix handling of phony statements, so they are actually emitted. By @sagudev in #6328.
- Added
gl_DrawIDto glsl andDrawIndexto spv. By @ChosenName in #6325. - Matrices can now be indexed by value (#4337), and indexing arrays by value no longer causes excessive spilling (#6358). By @jimblandy in #6390.
- Add support for
textureQueryLevelsto the GLSL parser. By @magcius in #6325. - Fix unescaped identifiers in the Metal backend shader I/O structures causing shader miscompilation. By @ErichDonGubler in #6438.
General
- If GL context creation fails retry with GLES. By @Rapdorian in #5996.
- Fix profiling with
tracy. By @waywardmonkeys in #5988. - As a workaround for issue #4905,
wgpu-coreis undocumented unless--cfg wgpu_core_docfeature is enabled. By @kpreid in #5987. - Bump MSRV for
d3d12/naga/wgpu-core/wgpu-hal/wgpu-types' to 1.76. By @Wumpf in #6003. - Print requested and supported usages on
UnsupportedUsageerror. By @VladasZ in #6007. - Fix function for checking bind compatibility to error instead of panic. By @sagudev #6012.
- Deduplicate bind group layouts that are created from pipelines with "auto" layouts. By @teoxoy #6049.
- Fix crash when dropping the surface after the device. By @Wumpf in #6052.
- Fix error message that is thrown in create_render_pass to no longer say
compute_pass. By @matthew-wong1 #6041. - Document
wgpu_halbounds-checking promises, and adaptwgpu_core's lazy initialization logic to the slightly weaker-than-expected guarantees. By @jimblandy in #6201. - Raise validation error instead of panicking in
{Render,Compute}Pipeline::get_bind_group_layouton native / WebGL. By @BGR360 in #6280. - BREAKING: Remove the last exposed C symbols in project, located in
wgpu_core::render::bundle::bundle_ffi, to allow multiple versions of WGPU to compile together. By @ErichDonGubler in #6272. - Call
flush_mapped_rangeswhen unmapping write-mapped buffers. By @teoxoy in #6089. - When mapping buffers for reading, mark buffers as initialized only when they have
MAP_WRITEusage. By @teoxoy in #6178. - Add a separate pipeline constants error. By @teoxoy in #6094.
- Ensure safety of indirect dispatch by injecting a compute shader that validates the content of the indirect buffer. By @teoxoy in #5714.
GLES / OpenGL
- Fix GL debug message callbacks not being properly cleaned up (causing UB). By @Imberflur in #6114.
- Fix calling
slice::from_raw_partswith unaligned pointers in push constant handling. By @Imberflur in #6341. - Optimise fence checking when
Queue::submitis called many times per frame. By @Dinnerbone in #6427.
WebGPU
- Fix JS
TypeErrorexception inInstance::request_adapterwhen browser doesn't support WebGPU butwgpunot compiled withwebglsupport. By @BGR360 in #6197.
Vulkan
- Avoid undefined behaviour with adversarial debug label. By @DJMcNab in #6257.
- Add
.index_type(vk::IndexType::NONE_KHR)when creatingAccelerationStructureGeometryTrianglesDataKHRin the raytraced triangle example to prevent a validation error. By @Vecvec in #6282.
Changes
wgpu_hal::gles::Adapter::new_externalnow requires the context to be current when dropping the adapter and related objects. By @Imberflur in #6114.- Reduce the amount of debug and trace logs emitted by wgpu-core and wgpu-hal. By @nical in #6065.
- Rename
Rg11b10FloattoRg11b10Ufloat. By @sagudev in #6108. - Invalidate the device when we encounter driver-induced device loss or on unexpected errors. By @teoxoy in #6229.
- Make Vulkan error handling more robust. By @teoxoy in #6119.
- Add bounds checking to Buffer slice method. By @beholdnec in #6432.
- Replace
impl From<StorageFormat> for ScalarKindwithimpl From<StorageFormat> for Scalarso that byte width is included. By @atlv24 in #6451.
Internal
- Tracker simplifications. By @teoxoy in #6073 & #6088.
- D3D12 cleanup. By @teoxoy in #6200.
- Use
ManuallyDropin remaining places. By @teoxoy in #6092. - Move out invalidity from the
Registry. By @teoxoy in #6243. - Remove
backendfrom ID. By @teoxoy in #6263.
HAL
- Change the inconsistent
DropGuardbased API on Vulkan and GLES to a consistent, callback-based one. By @jerzywilczek in #6164.
Documentation
- Removed some OpenGL and Vulkan references from
wgpu-typesdocumentation. Fixed Storage texel types in examples. By @Nelarius in #6271. - Used
wgpu::include_wgsl!(…)more in examples and tests. By @ErichDonGubler in #6326.
Dependency Updates
GLES
- Replace
winapicode in WGL wrapper to use thewindowscrate. By @MarijnS95 in #6006. - Update
glutinto0.31withglutin-winitcrate. By @MarijnS95 in #6150 and #6176. - Implement
Adapter::new_external()for WGL (just like EGL) to import an external OpenGL ES context. By @MarijnS95 in #6152.
DX12
- Replace
winapicode to use thewindowscrate. By @MarijnS95 in #5956 and #6173. - Get
num_workgroupsbuiltin working for indirect dispatches. By @teoxoy in #5730.