diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ee186b38f..eb1d19967f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,42 +40,147 @@ Bottom level categories: ## Unreleased +### New Features + +#### Naga + +- Parse `diagnostic(…)` directives, but don't implement any triggering rules yet. By @ErichDonGubler in [#6456](https://github.com/gfx-rs/wgpu/pull/6456). +- Fix an issue where `naga` CLI would incorrectly skip the first positional argument when `--stdin-file-path` was specified. By @ErichDonGubler in [#6480](https://github.com/gfx-rs/wgpu/pull/6480). + +#### Vulkan + +- Allow using some 32-bit floating-point atomic operations (load, store, add, sub, exchange) in shaders. It requires the extension `VK_EXT_shader_atomic_float`. By @AsherJingkongChen in [#6234](https://github.com/gfx-rs/wgpu/pull/6234) + +#### Metal + +- Allow using some 32-bit floating-point atomic operations (load, store, add, sub, exchange) in shaders. It requires Metal 3.0+ with Apple 7, 8, 9 or Mac 2. By @AsherJingkongChen in [#6234](https://github.com/gfx-rs/wgpu/pull/6234) + +### Changes + +#### HAL + +- Change the `DropCallback` API to use `FnOnce` instead of `FnMut`. By @jerzywilczek in [#6482](https://github.com/gfx-rs/wgpu/pull/6482) + +## 23.0.0 (2024-10-25) + +### 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][nodejs-webgpu-interest] and [Deno][deno_webgpu-crate-manifest] have communities that are very interested in providing WebGPU! WebGPU is slowly [eating the world][eat-the-world-meaning], 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. + +[nodejs-webgpu-interest]: https://github.com/orgs/nodejs/discussions/41994 +[deno_webgpu-crate-manifest]: https://github.com/gfx-rs/wgpu/tree/64a61ee5c69569bbb3db03563997e88a229eba17/deno_webgpu#deno_webgpu +[eat-the-world-meaning]: https://www.quora.com/What-did-Marc-Andreessen-mean-when-he-said-that-software-is-eating-the-world + +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 this: + +```wgsl +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: + +```wgsl +const arr: array = 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`. +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`. -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. +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](https://github.com/gfx-rs/wgpu/pull/6069), [#6099](https://github.com/gfx-rs/wgpu/pull/6099), [#6100](https://github.com/gfx-rs/wgpu/pull/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. +`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. +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. -By @teoxoy [#6134](https://github.com/gfx-rs/wgpu/pull/6134). +By @teoxoy in [#6134](https://github.com/gfx-rs/wgpu/pull/6134). #### `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>`, -so most code should still work the same. +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>`, so most code should still work the same. + +By @bradwerth in [#6216](https://github.com/gfx-rs/wgpu/pull/6216). + +#### `entry_point`s are now `Option`al -By @bradwerth [#6216](https://github.com/gfx-rs/wgpu/pull/6216). +One of the changes in the WebGPU spec. (from [about this time last year][optional-entrypoint-in-spec] 😅) 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: + +```wgsl +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: + +```wgsl +// 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() { /* … */ } +``` + +[optional-entrypoint-in-spec]: https://github.com/gpuweb/gpuweb/issues/4342 + +#### 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](https://github.com/gfx-rs/wgpu/pull/6006). ### New Features @@ -93,29 +198,28 @@ By @bradwerth [#6216](https://github.com/gfx-rs/wgpu/pull/6216). #### General -- Add `VideoFrame` to `ExternalImageSource` enum. By @jprochazk in [#6170](https://github.com/gfx-rs/wgpu/pull/6170) -- Add `wgpu::util::new_instance_with_webgpu_detection` & `wgpu::util::is_browser_webgpu_supported` to make it easier to support WebGPU & WebGL in the same binary. By @wumpf in [#6371](https://github.com/gfx-rs/wgpu/pull/6371) +- Add `VideoFrame` to `ExternalImageSource` enum. By @jprochazk in [#6170](https://github.com/gfx-rs/wgpu/pull/6170). +- Add `wgpu::util::new_instance_with_webgpu_detection` & `wgpu::util::is_browser_webgpu_supported` to make it easier to support WebGPU & WebGL in the same binary. By @wumpf in [#6371](https://github.com/gfx-rs/wgpu/pull/6371). #### Vulkan -- Allow using [VK_GOOGLE_display_timing](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_GOOGLE_display_timing.html) unsafely with the `VULKAN_GOOGLE_DISPLAY_TIMING` feature. By @DJMcNab in [#6149](https://github.com/gfx-rs/wgpu/pull/6149) -- Allow using some 32-bit floating-point atomic operations (load, store, add, sub, exchange) in shaders. It requires the extension `VK_EXT_shader_atomic_float`. By @AsherJingkongChen in [#6234](https://github.com/gfx-rs/wgpu/pull/6234) +- Allow using [VK_GOOGLE_display_timing](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_GOOGLE_display_timing.html) unsafely with the `VULKAN_GOOGLE_DISPLAY_TIMING` feature. By @DJMcNab in [#6149](https://github.com/gfx-rs/wgpu/pull/6149). #### Metal -- Allow using some 32-bit floating-point atomic operations (load, store, add, sub, exchange) in shaders. It requires Metal 3.0+ with Apple 7, 8, 9 or Mac 2. By @AsherJingkongChen in [#6234](https://github.com/gfx-rs/wgpu/pull/6234) -- Implement `atomicCompareExchangeWeak`. By @AsherJingkongChen in [#6265](https://github.com/gfx-rs/wgpu/pull/6265) +- Implement `atomicCompareExchangeWeak`. By @AsherJingkongChen in [#6265](https://github.com/gfx-rs/wgpu/pull/6265). +- Unless an explicit `CAMetalLayer` is provided, surfaces now render to a sublayer. This improves resizing behavior, fixing glitches during on window resize. By @madsmtm in [#6107](https://github.com/gfx-rs/wgpu/pull/6107). ### Bug Fixes -- Fix incorrect hlsl image output type conversion. By @atlv24 in [#6123](https://github.com/gfx-rs/wgpu/pull/6123) +- Fix incorrect hlsl image output type conversion. By @atlv24 in [#6123](https://github.com/gfx-rs/wgpu/pull/6123). #### Naga - SPIR-V frontend splats depth texture sample and load results. Fixes [issue #4551](https://github.com/gfx-rs/wgpu/issues/4551). By @schell in [#6384](https://github.com/gfx-rs/wgpu/pull/6384). - Accept only `vec3` (not `vecN`) for the `cross` built-in. By @ErichDonGubler in [#6171](https://github.com/gfx-rs/wgpu/pull/6171). - Configure `SourceLanguage` when enabling debug info in SPV-out. By @kvark in [#6256](https://github.com/gfx-rs/wgpu/pull/6256). -- Per-polygon and flat inputs should not be considered subgroup uniform. By @magcius in [#6276](https://github.com/gfx-rs/wgpu/pull/6276). +- Do not consider per-polygon and flat inputs subgroup uniform. By @magcius in [#6276](https://github.com/gfx-rs/wgpu/pull/6276). - Validate all swizzle components are either color (rgba) or dimension (xyzw) in WGSL. By @sagudev in [#6187](https://github.com/gfx-rs/wgpu/pull/6187). - Fix detection of shl overflows to detect arithmetic overflows. By @sagudev in [#6186](https://github.com/gfx-rs/wgpu/pull/6186). - Fix type parameters to vec/mat type constructors to also support aliases. By @sagudev in [#6189](https://github.com/gfx-rs/wgpu/pull/6189). @@ -128,28 +232,28 @@ By @bradwerth [#6216](https://github.com/gfx-rs/wgpu/pull/6216). #### General -- If GL context creation fails retry with GLES. By @Rapdorian in [#5996](https://github.com/gfx-rs/wgpu/pull/5996) -- Fix profiling with `tracy`. By @waywardmonkeys in [#5988](https://github.com/gfx-rs/wgpu/pull/5988) -- As a workaround for [issue #4905](https://github.com/gfx-rs/wgpu/issues/4905), `wgpu-core` is undocumented unless `--cfg wgpu_core_doc` feature is enabled. By @kpreid in [#5987](https://github.com/gfx-rs/wgpu/pull/5987) -- Bump MSRV for `d3d12`/`naga`/`wgpu-core`/`wgpu-hal`/`wgpu-types`' to 1.76. By @wumpf in [#6003](https://github.com/gfx-rs/wgpu/pull/6003) -- Print requested and supported usages on `UnsupportedUsage` error. By @VladasZ in [#6007](https://github.com/gfx-rs/wgpu/pull/6007) -- Fix function for checking bind compatibility to error instead of panic. By @sagudev [#6012](https://github.com/gfx-rs/wgpu/pull/6012) -- Deduplicate bind group layouts that are created from pipelines with "auto" layouts. By @teoxoy [#6049](https://github.com/gfx-rs/wgpu/pull/6049) -- Fix crash when dropping the surface after the device. By @wumpf in [#6052](https://github.com/gfx-rs/wgpu/pull/6052) -- Fix error message that is thrown in create_render_pass to no longer say `compute_pass`. By @matthew-wong1 [#6041](https://github.com/gfx-rs/wgpu/pull/6041) -- Document `wgpu_hal` bounds-checking promises, and adapt `wgpu_core`'s lazy initialization logic to the slightly weaker-than-expected guarantees. By @jimblandy in [#6201](https://github.com/gfx-rs/wgpu/pull/6201) +- If GL context creation fails retry with GLES. By @Rapdorian in [#5996](https://github.com/gfx-rs/wgpu/pull/5996). +- Fix profiling with `tracy`. By @waywardmonkeys in [#5988](https://github.com/gfx-rs/wgpu/pull/5988). +- As a workaround for [issue #4905](https://github.com/gfx-rs/wgpu/issues/4905), `wgpu-core` is undocumented unless `--cfg wgpu_core_doc` feature is enabled. By @kpreid in [#5987](https://github.com/gfx-rs/wgpu/pull/5987). +- Bump MSRV for `d3d12`/`naga`/`wgpu-core`/`wgpu-hal`/`wgpu-types`' to 1.76. By @wumpf in [#6003](https://github.com/gfx-rs/wgpu/pull/6003). +- Print requested and supported usages on `UnsupportedUsage` error. By @VladasZ in [#6007](https://github.com/gfx-rs/wgpu/pull/6007). +- Fix function for checking bind compatibility to error instead of panic. By @sagudev [#6012](https://github.com/gfx-rs/wgpu/pull/6012). +- Deduplicate bind group layouts that are created from pipelines with "auto" layouts. By @teoxoy [#6049](https://github.com/gfx-rs/wgpu/pull/6049). +- Fix crash when dropping the surface after the device. By @wumpf in [#6052](https://github.com/gfx-rs/wgpu/pull/6052). +- Fix error message that is thrown in create_render_pass to no longer say `compute_pass`. By @matthew-wong1 [#6041](https://github.com/gfx-rs/wgpu/pull/6041). +- Document `wgpu_hal` bounds-checking promises, and adapt `wgpu_core`'s lazy initialization logic to the slightly weaker-than-expected guarantees. By @jimblandy in [#6201](https://github.com/gfx-rs/wgpu/pull/6201). - Raise validation error instead of panicking in `{Render,Compute}Pipeline::get_bind_group_layout` on native / WebGL. By @bgr360 in [#6280](https://github.com/gfx-rs/wgpu/pull/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](https://github.com/gfx-rs/wgpu/pull/6272). - Call `flush_mapped_ranges` when unmapping write-mapped buffers. By @teoxoy in [#6089](https://github.com/gfx-rs/wgpu/pull/6089). - When mapping buffers for reading, mark buffers as initialized only when they have `MAP_WRITE` usage. By @teoxoy in [#6178](https://github.com/gfx-rs/wgpu/pull/6178). - Add a separate pipeline constants error. By @teoxoy in [#6094](https://github.com/gfx-rs/wgpu/pull/6094). -- Ensure safety of indirect dispatch by injecting a compute shader that validates the content of the indirect buffer. By @teoxoy in [#5714](https://github.com/gfx-rs/wgpu/pull/5714) +- Ensure safety of indirect dispatch by injecting a compute shader that validates the content of the indirect buffer. By @teoxoy in [#5714](https://github.com/gfx-rs/wgpu/pull/5714). #### GLES / OpenGL -- Fix GL debug message callbacks not being properly cleaned up (causing UB). By @Imberflur in [#6114](https://github.com/gfx-rs/wgpu/pull/6114) -- Fix calling `slice::from_raw_parts` with unaligned pointers in push constant handling. By @Imberflur in [#6341](https://github.com/gfx-rs/wgpu/pull/6341) -- Optimise fence checking when `Queue::submit` is called many times per frame. By @dinnerbone in [#6427](https://github.com/gfx-rs/wgpu/pull/6427) +- Fix GL debug message callbacks not being properly cleaned up (causing UB). By @Imberflur in [#6114](https://github.com/gfx-rs/wgpu/pull/6114). +- Fix calling `slice::from_raw_parts` with unaligned pointers in push constant handling. By @Imberflur in [#6341](https://github.com/gfx-rs/wgpu/pull/6341). +- Optimise fence checking when `Queue::submit` is called many times per frame. By @dinnerbone in [#6427](https://github.com/gfx-rs/wgpu/pull/6427). #### WebGPU @@ -157,14 +261,14 @@ By @bradwerth [#6216](https://github.com/gfx-rs/wgpu/pull/6216). #### Vulkan -- Vulkan debug labels assumed no interior nul byte. By @DJMcNab in [#6257](https://github.com/gfx-rs/wgpu/pull/6257) -- Add `.index_type(vk::IndexType::NONE_KHR)` when creating `AccelerationStructureGeometryTrianglesDataKHR` in the raytraced triangle example to prevent a validation error. By @Vecvec in [#6282](https://github.com/gfx-rs/wgpu/pull/6282) +- Avoid undefined behaviour with adversarial debug label. By @DJMcNab in [#6257](https://github.com/gfx-rs/wgpu/pull/6257). +- Add `.index_type(vk::IndexType::NONE_KHR)` when creating `AccelerationStructureGeometryTrianglesDataKHR` in the raytraced triangle example to prevent a validation error. By @Vecvec in [#6282](https://github.com/gfx-rs/wgpu/pull/6282). ### Changes - `wgpu_hal::gles::Adapter::new_external` now requires the context to be current when dropping the adapter and related objects. By @Imberflur in [#6114](https://github.com/gfx-rs/wgpu/pull/6114). -- Reduce the amount of debug and trace logs emitted by wgpu-core and wgpu-hal. By @nical in [#6065](https://github.com/gfx-rs/wgpu/issues/6065) -- `Rg11b10Float` is renamed to `Rg11b10Ufloat`. By @sagudev in [#6108](https://github.com/gfx-rs/wgpu/pull/6108) +- Reduce the amount of debug and trace logs emitted by wgpu-core and wgpu-hal. By @nical in [#6065](https://github.com/gfx-rs/wgpu/issues/6065). +- Rename `Rg11b10Float` to `Rg11b10Ufloat`. By @sagudev in [#6108](https://github.com/gfx-rs/wgpu/pull/6108). - Invalidate the device when we encounter driver-induced device loss or on unexpected errors. By @teoxoy in [#6229](https://github.com/gfx-rs/wgpu/pull/6229). - Make Vulkan error handling more robust. By @teoxoy in [#6119](https://github.com/gfx-rs/wgpu/pull/6119). - Add bounds checking to Buffer slice method. By @beholdnec in [#6432](https://github.com/gfx-rs/wgpu/pull/6432). @@ -180,29 +284,29 @@ By @bradwerth [#6216](https://github.com/gfx-rs/wgpu/pull/6216). #### HAL -- Change the inconsistent `DropGuard` based API on Vulkan and GLES to a consistent, callback-based one. By @jerzywilczek in [#6164](https://github.com/gfx-rs/wgpu/pull/6164) +- Change the inconsistent `DropGuard` based API on Vulkan and GLES to a consistent, callback-based one. By @jerzywilczek in [#6164](https://github.com/gfx-rs/wgpu/pull/6164). ### Documentation -- Removed some OpenGL and Vulkan references from `wgpu-types` documentation. Fixed Storage texel types in examples. By @Nelarius in [#6271](https://github.com/gfx-rs/wgpu/pull/6271) +- Removed some OpenGL and Vulkan references from `wgpu-types` documentation. Fixed Storage texel types in examples. By @Nelarius in [#6271](https://github.com/gfx-rs/wgpu/pull/6271). - Used `wgpu::include_wgsl!(…)` more in examples and tests. By @ErichDonGubler in [#6326](https://github.com/gfx-rs/wgpu/pull/6326). ### Dependency Updates #### GLES -- Replace `winapi` code in WGL wrapper to use the `windows` crate. By @MarijnS95 in [#6006](https://github.com/gfx-rs/wgpu/pull/6006) -- Update `glutin` to `0.31` with `glutin-winit` crate. By @MarijnS95 in [#6150](https://github.com/gfx-rs/wgpu/pull/6150) and [#6176](https://github.com/gfx-rs/wgpu/pull/6176) -- Implement `Adapter::new_external()` for WGL (just like EGL) to import an external OpenGL ES context. By @MarijnS95 in [#6152](https://github.com/gfx-rs/wgpu/pull/6152) +- Replace `winapi` code in WGL wrapper to use the `windows` crate. By @MarijnS95 in [#6006](https://github.com/gfx-rs/wgpu/pull/6006). +- Update `glutin` to `0.31` with `glutin-winit` crate. By @MarijnS95 in [#6150](https://github.com/gfx-rs/wgpu/pull/6150) and [#6176](https://github.com/gfx-rs/wgpu/pull/6176). +- Implement `Adapter::new_external()` for WGL (just like EGL) to import an external OpenGL ES context. By @MarijnS95 in [#6152](https://github.com/gfx-rs/wgpu/pull/6152). #### DX12 -- Replace `winapi` code to use the `windows` crate. By @MarijnS95 in [#5956](https://github.com/gfx-rs/wgpu/pull/5956) and [#6173](https://github.com/gfx-rs/wgpu/pull/6173) -- Get `num_workgroups` builtin working for indirect dispatches. By @teoxoy in [#5730](https://github.com/gfx-rs/wgpu/pull/5730) +- Replace `winapi` code to use the `windows` crate. By @MarijnS95 in [#5956](https://github.com/gfx-rs/wgpu/pull/5956) and [#6173](https://github.com/gfx-rs/wgpu/pull/6173). +- Get `num_workgroups` builtin working for indirect dispatches. By @teoxoy in [#5730](https://github.com/gfx-rs/wgpu/pull/5730). #### HAL -- Update `parking_lot` to `0.12`. By @mahkoh in [#6287](https://github.com/gfx-rs/wgpu/pull/6287) +- Update `parking_lot` to `0.12`. By @mahkoh in [#6287](https://github.com/gfx-rs/wgpu/pull/6287). ## 22.0.0 (2024-07-17) diff --git a/Cargo.lock b/Cargo.lock index 04d2b3c037..92035455d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1739,7 +1739,7 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock-analyzer" -version = "22.0.0" +version = "23.0.0" dependencies = [ "anyhow", "ron", @@ -1875,7 +1875,7 @@ dependencies = [ [[package]] name = "naga" -version = "22.0.0" +version = "23.0.0" dependencies = [ "arbitrary", "arrayvec", @@ -1905,13 +1905,14 @@ dependencies = [ [[package]] name = "naga-cli" -version = "22.0.0" +version = "23.0.0" dependencies = [ "anyhow", "argh", "bincode", "codespan-reporting", "env_logger", + "log", "naga", ] @@ -2271,7 +2272,7 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "player" -version = "22.0.0" +version = "23.0.0" dependencies = [ "env_logger", "log", @@ -3564,7 +3565,7 @@ dependencies = [ [[package]] name = "wgpu" -version = "22.0.0" +version = "23.0.0" dependencies = [ "arrayvec", "cfg_aliases", @@ -3588,7 +3589,7 @@ dependencies = [ [[package]] name = "wgpu-benchmark" -version = "22.0.0" +version = "23.0.0" dependencies = [ "bincode", "bytemuck", @@ -3605,7 +3606,7 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "22.0.0" +version = "23.0.0" dependencies = [ "arrayvec", "bit-vec", @@ -3631,7 +3632,7 @@ dependencies = [ [[package]] name = "wgpu-examples" -version = "22.0.0" +version = "23.0.0" dependencies = [ "bytemuck", "cfg-if", @@ -3662,7 +3663,7 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "22.0.0" +version = "23.0.0" dependencies = [ "android_system_properties", "arrayvec", @@ -3712,7 +3713,7 @@ dependencies = [ [[package]] name = "wgpu-info" -version = "22.0.0" +version = "23.0.0" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -3725,7 +3726,7 @@ dependencies = [ [[package]] name = "wgpu-macros" -version = "22.0.0" +version = "23.0.0" dependencies = [ "heck 0.5.0", "quote", @@ -3734,7 +3735,7 @@ dependencies = [ [[package]] name = "wgpu-test" -version = "22.0.0" +version = "23.0.0" dependencies = [ "anyhow", "arrayvec", @@ -3769,7 +3770,7 @@ dependencies = [ [[package]] name = "wgpu-types" -version = "22.0.0" +version = "23.0.0" dependencies = [ "bitflags 2.6.0", "js-sys", diff --git a/Cargo.toml b/Cargo.toml index 1e0bb77edf..0a5481abfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,27 +47,27 @@ keywords = ["graphics"] license = "MIT OR Apache-2.0" homepage = "https://wgpu.rs/" repository = "https://github.com/gfx-rs/wgpu" -version = "22.0.0" +version = "23.0.0" authors = ["gfx-rs developers"] [workspace.dependencies.wgc] package = "wgpu-core" path = "./wgpu-core" -version = "22.0.0" +version = "23.0.0" [workspace.dependencies.wgt] package = "wgpu-types" path = "./wgpu-types" -version = "22.0.0" +version = "23.0.0" [workspace.dependencies.hal] package = "wgpu-hal" path = "./wgpu-hal" -version = "22.0.0" +version = "23.0.0" [workspace.dependencies.naga] path = "./naga" -version = "22.0.0" +version = "23.0.0" [workspace.dependencies] anyhow = "1.0.91" @@ -126,11 +126,11 @@ static_assertions = "1.1.0" strum = { version = "0.25.0", features = ["derive"] } tracy-client = "0.17" thiserror = "1.0.65" -wgpu = { version = "22.0.0", path = "./wgpu", default-features = false } -wgpu-core = { version = "22.0.0", path = "./wgpu-core" } -wgpu-macros = { version = "22.0.0", path = "./wgpu-macros" } -wgpu-test = { version = "22.0.0", path = "./tests" } -wgpu-types = { version = "22.0.0", path = "./wgpu-types" } +wgpu = { version = "23.0.0", path = "./wgpu", default-features = false } +wgpu-core = { version = "23.0.0", path = "./wgpu-core" } +wgpu-macros = { version = "23.0.0", path = "./wgpu-macros" } +wgpu-test = { version = "23.0.0", path = "./tests" } +wgpu-types = { version = "23.0.0", path = "./wgpu-types" } winit = { version = "0.29", features = ["android-native-activity"] } # Metal dependencies diff --git a/RELEASE.md b/RELEASE.md index 561c7fcad4..768167d12a 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -10,7 +10,7 @@ We do a patch releases as needed in the weeks between major releases. Once a new Anyone can perform most of these steps, except actually publishing the crates. -Currently only @kvark and @cwfitzgerald can publish all crates. @grovesNL can also publish `wgpu` crates. @jimblandy can publish `naga` crates. @msiglreith can publish `d3d12`. +Currently only @kvark and @cwfitzgerald can publish all crates. @grovesNL can also publish `wgpu` crates. @jimblandy can publish `naga` crates. ## Major Release Process @@ -24,7 +24,6 @@ Approx 1 Week Before: Day of Release: - Update all crates to be the new version. We bump all versions even if there were no changes. - - `d3d12` - `naga` - `naga-cli` - `wgpu-types` @@ -38,7 +37,6 @@ Day of Release: - Checkout `trunk` with the merged PR. - Publish! These commands can be pasted directly into your terminal in a single command, and they will publish everything. ```bash - cargo publish -p d3d12 cargo publish -p naga cargo publish -p naga-cli cargo publish -p wgpu-types diff --git a/naga-cli/Cargo.toml b/naga-cli/Cargo.toml index e9abb82d26..02f68cc02a 100644 --- a/naga-cli/Cargo.toml +++ b/naga-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "naga-cli" -version = "22.0.0" +version = "23.0.0" authors = ["gfx-rs developers"] edition = "2021" description = "Shader translation command line tool" @@ -23,9 +23,10 @@ codespan-reporting.workspace = true env_logger.workspace = true argh.workspace = true anyhow.workspace = true +log.workspace = true [dependencies.naga] -version = "22.0.0" +version = "23.0.0" path = "../naga" features = [ "compact", diff --git a/naga-cli/src/bin/naga.rs b/naga-cli/src/bin/naga.rs index f19bd15d22..e7d007d018 100644 --- a/naga-cli/src/bin/naga.rs +++ b/naga-cli/src/bin/naga.rs @@ -375,7 +375,10 @@ impl fmt::Display for CliError { impl std::error::Error for CliError {} fn run() -> anyhow::Result<()> { - env_logger::init(); + env_logger::builder() + .filter_level(log::LevelFilter::Info) + .parse_default_env() + .init(); // Parse commandline arguments let args: Args = argh::from_env(); @@ -448,13 +451,15 @@ fn run() -> anyhow::Result<()> { return bulk_validate(args, ¶ms); } - let (input_path, input) = if let Some(path) = args.files.first() { - let path = Path::new(path); - (path, fs::read(path)?) - } else if let Some(path) = &args.stdin_file_path { + let mut files = args.files.iter(); + + let (input_path, input) = if let Some(path) = args.stdin_file_path.as_ref() { let mut input = vec![]; std::io::stdin().lock().read_to_end(&mut input)?; (Path::new(path), input) + } else if let Some(path) = files.next() { + let path = Path::new(path); + (path, fs::read(path)?) } else { return Err(CliError("Input file path is not specified").into()); }; @@ -489,12 +494,12 @@ fn run() -> anyhow::Result<()> { } } - let output_paths = args.files.get(1..).unwrap_or(&[]); + let output_paths = files; // Decide which capabilities our output formats can support. let validation_caps = output_paths - .iter() + .clone() .fold(naga::valid::Capabilities::all(), |caps, path| { use naga::valid::Capabilities as C; let missing = match Path::new(path).extension().and_then(|ex| ex.to_str()) { @@ -564,7 +569,7 @@ fn run() -> anyhow::Result<()> { // // If the user asked for output, don't stop: some output formats (".txt", // ".dot", ".bin") can be generated even without a `ModuleInfo`. - if output_paths.is_empty() { + if output_paths.clone().next().is_none() { if info.is_some() { println!("Validation successful"); return Ok(()); diff --git a/naga/Cargo.toml b/naga/Cargo.toml index 85c6c4847c..16682e5268 100644 --- a/naga/Cargo.toml +++ b/naga/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "naga" -version = "22.0.0" +version = "23.0.0" authors = ["gfx-rs developers"] edition = "2021" description = "Shader translation infrastructure" diff --git a/naga/fuzz/Cargo.toml b/naga/fuzz/Cargo.toml index c4dd8cd1c1..f34a6f92e9 100644 --- a/naga/fuzz/Cargo.toml +++ b/naga/fuzz/Cargo.toml @@ -15,7 +15,7 @@ libfuzzer-sys = "0.4" [target.'cfg(not(any(target_arch = "wasm32", target_os = "ios")))'.dependencies.naga] path = ".." -version = "22.0.0" +version = "23.0.0" features = ["arbitrary", "spv-in", "wgsl-in", "glsl-in"] [[bin]] diff --git a/naga/src/back/spv/block.rs b/naga/src/back/spv/block.rs index fdfba1eaad..7543ea7623 100644 --- a/naga/src/back/spv/block.rs +++ b/naga/src/back/spv/block.rs @@ -24,7 +24,7 @@ fn get_dimension(type_inner: &crate::TypeInner) -> Dimension { /// types are simply the direct SPIR-V analog of the Naga IR's. But in some /// cases, the Naga IR and SPIR-V types need to diverge. /// -/// This enum specifies how [`BlockContext::write_expression_pointer`] should +/// This enum specifies how [`BlockContext::write_access_chain`] should /// choose a SPIR-V result type for the `OpAccessChain` it generates, based on /// the type of the given Naga IR [`Expression`] it's generating code for. /// @@ -68,7 +68,7 @@ enum AccessTypeAdjustment { /// The results of emitting code for a left-hand-side expression. /// -/// On success, `write_expression_pointer` returns one of these. +/// On success, `write_access_chain` returns one of these. enum ExpressionPointer { /// The pointer to the expression's value is available, as the value of the /// expression with the given id. @@ -407,7 +407,7 @@ impl<'w> BlockContext<'w> { } => { // Only binding arrays in the `Handle` address space will take // this path, since we handled the `Pointer` case above. - let result_id = match self.write_expression_pointer( + let result_id = match self.write_access_chain( expr_handle, block, AccessTypeAdjustment::IntroducePointer( @@ -498,7 +498,7 @@ impl<'w> BlockContext<'w> { } => { // Only binding arrays in the `Handle` address space will take // this path, since we handled the `Pointer` case above. - let result_id = match self.write_expression_pointer( + let result_id = match self.write_access_chain( expr_handle, block, AccessTypeAdjustment::IntroducePointer( @@ -1751,7 +1751,7 @@ impl<'w> BlockContext<'w> { /// /// On success, the return value is an [`ExpressionPointer`] value; see the /// documentation for that type. - fn write_expression_pointer( + fn write_access_chain( &mut self, mut expr_handle: Handle, block: &mut Block, @@ -1982,7 +1982,7 @@ impl<'w> BlockContext<'w> { access_type_adjustment: AccessTypeAdjustment, result_type_id: Word, ) -> Result { - match self.write_expression_pointer(pointer, block, access_type_adjustment)? { + match self.write_access_chain(pointer, block, access_type_adjustment)? { ExpressionPointer::Ready { pointer_id } => { let id = self.gen_id(); let atomic_space = @@ -2603,7 +2603,7 @@ impl<'w> BlockContext<'w> { } Statement::Store { pointer, value } => { let value_id = self.cached[value]; - match self.write_expression_pointer( + match self.write_access_chain( pointer, &mut block, AccessTypeAdjustment::None, @@ -2703,7 +2703,7 @@ impl<'w> BlockContext<'w> { self.cached[result] = id; } - let pointer_id = match self.write_expression_pointer( + let pointer_id = match self.write_access_chain( pointer, &mut block, AccessTypeAdjustment::None, @@ -2923,7 +2923,7 @@ impl<'w> BlockContext<'w> { .write_barrier(crate::Barrier::WORK_GROUP, &mut block); let result_type_id = self.get_expression_type_id(&self.fun_info[result].ty); // Embed the body of - match self.write_expression_pointer( + match self.write_access_chain( pointer, &mut block, AccessTypeAdjustment::None, diff --git a/naga/src/diagnostic_filter.rs b/naga/src/diagnostic_filter.rs new file mode 100644 index 0000000000..e2683b8fa9 --- /dev/null +++ b/naga/src/diagnostic_filter.rs @@ -0,0 +1,97 @@ +//! [`DiagnosticFilter`]s and supporting functionality. + +/// A severity set on a [`DiagnosticFilter`]. +/// +/// +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum Severity { + Off, + Info, + Warning, + Error, +} + +impl Severity { + const ERROR: &'static str = "error"; + const WARNING: &'static str = "warning"; + const INFO: &'static str = "info"; + const OFF: &'static str = "off"; + + /// Convert from a sentinel word in WGSL into its associated [`Severity`], if possible. + pub fn from_ident(s: &str) -> Option { + Some(match s { + Self::ERROR => Self::Error, + Self::WARNING => Self::Warning, + Self::INFO => Self::Info, + Self::OFF => Self::Off, + _ => return None, + }) + } + + /// Checks whether this severity is [`Self::Error`]. + /// + /// Naga does not yet support diagnostic items at lesser severities than + /// [`Severity::Error`]. When this is implemented, this method should be deleted, and the + /// severity should be used directly for reporting diagnostics. + #[cfg(feature = "wgsl-in")] + pub(crate) fn report_diag( + self, + err: E, + log_handler: impl FnOnce(E, log::Level), + ) -> Result<(), E> { + let log_level = match self { + Severity::Off => return Ok(()), + + // NOTE: These severities are not yet reported. + Severity::Info => log::Level::Info, + Severity::Warning => log::Level::Warn, + + Severity::Error => return Err(err), + }; + log_handler(err, log_level); + Ok(()) + } +} + +/// A filterable triggering rule in a [`DiagnosticFilter`]. +/// +/// +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum FilterableTriggeringRule { + DerivativeUniformity, +} + +impl FilterableTriggeringRule { + const DERIVATIVE_UNIFORMITY: &'static str = "derivative_uniformity"; + + /// Convert from a sentinel word in WGSL into its associated [`FilterableTriggeringRule`], if possible. + pub fn from_ident(s: &str) -> Option { + Some(match s { + Self::DERIVATIVE_UNIFORMITY => Self::DerivativeUniformity, + _ => return None, + }) + } + + /// Maps this [`FilterableTriggeringRule`] into the sentinel word associated with it in WGSL. + pub const fn to_ident(self) -> &'static str { + match self { + Self::DerivativeUniformity => Self::DERIVATIVE_UNIFORMITY, + } + } + + #[cfg(feature = "wgsl-in")] + pub(crate) const fn tracking_issue_num(self) -> u16 { + match self { + FilterableTriggeringRule::DerivativeUniformity => 5320, + } + } +} + +/// A filter that modifies how diagnostics are emitted for shaders. +/// +/// +#[derive(Clone, Debug)] +pub struct DiagnosticFilter { + pub new_severity: Severity, + pub triggering_rule: FilterableTriggeringRule, +} diff --git a/naga/src/front/wgsl/error.rs b/naga/src/front/wgsl/error.rs index 330c322700..f5e6332085 100644 --- a/naga/src/front/wgsl/error.rs +++ b/naga/src/front/wgsl/error.rs @@ -1,10 +1,10 @@ +use crate::diagnostic_filter::FilterableTriggeringRule; use crate::front::wgsl::parse::directive::enable_extension::{ EnableExtension, UnimplementedEnableExtension, }; use crate::front::wgsl::parse::directive::language_extension::{ LanguageExtension, UnimplementedLanguageExtension, }; -use crate::front::wgsl::parse::directive::{DirectiveKind, UnimplementedDirectiveKind}; use crate::front::wgsl::parse::lexer::Token; use crate::front::wgsl::Scalar; use crate::proc::{Alignment, ConstantEvaluatorError, ResolveError}; @@ -194,6 +194,7 @@ pub(crate) enum Error<'a> { UnknownConservativeDepth(Span), UnknownEnableExtension(Span, &'a str), UnknownLanguageExtension(Span, &'a str), + UnknownDiagnosticRuleName(Span), SizeAttributeTooLow(Span, u32), AlignAttributeTooLow(Span, Alignment), NonPowerOfTwoAlignAttribute(Span), @@ -276,10 +277,6 @@ pub(crate) enum Error<'a> { PipelineConstantIDValue(Span), NotBool(Span), ConstAssertFailed(Span), - DirectiveNotYetImplemented { - kind: UnimplementedDirectiveKind, - span: Span, - }, DirectiveAfterFirstGlobalDecl { directive_span: Span, }, @@ -295,6 +292,13 @@ pub(crate) enum Error<'a> { kind: UnimplementedLanguageExtension, span: Span, }, + DiagnosticInvalidSeverity { + severity_control_name_span: Span, + }, + DiagnosticNotYetImplemented { + triggering_rule: FilterableTriggeringRule, + span: Span, + }, } #[derive(Clone, Debug)] @@ -562,6 +566,15 @@ impl<'a> Error<'a> { ) .into()], }, + Error::UnknownDiagnosticRuleName(span) => ParseError { + message: format!("unknown `diagnostic(…)` rule name `{}`", &source[span]), + labels: vec![(span, "not a valid diagnostic rule name".into())], + notes: vec![concat!( + "See available trigger rules at ", + "." + ) + .into()], + }, Error::SizeAttributeTooLow(bad_span, min_size) => ParseError { message: format!("struct member size must be at least {min_size}"), labels: vec![(bad_span, format!("must be at least {min_size}").into())], @@ -914,24 +927,6 @@ impl<'a> Error<'a> { labels: vec![(span, "evaluates to false".into())], notes: vec![], }, - Error::DirectiveNotYetImplemented { kind, span } => ParseError { - message: format!( - "the `{}` directive is not yet implemented", - DirectiveKind::Unimplemented(kind).to_ident() - ), - labels: vec![( - span, - "this global directive is standard, but not yet implemented".into(), - )], - notes: vec![format!( - concat!( - "Let Naga maintainers know that you ran into this at ", - ", ", - "so they can prioritize it!" - ), - kind.tracking_issue_num() - )], - }, Error::DirectiveAfterFirstGlobalDecl { directive_span } => ParseError { message: "expected global declaration, but found a global directive".into(), labels: vec![( @@ -1008,6 +1003,38 @@ impl<'a> Error<'a> { kind.tracking_issue_num() )], }, + Error::DiagnosticInvalidSeverity { + severity_control_name_span, + } => ParseError { + message: "invalid `diagnostic(…)` severity".into(), + labels: vec![( + severity_control_name_span, + "not a valid severity level".into(), + )], + notes: vec![concat!( + "See available severities at ", + "." + ) + .into()], + }, + Error::DiagnosticNotYetImplemented { + triggering_rule, + span, + } => ParseError { + message: format!( + "the `{}` diagnostic filter is not yet supported", + triggering_rule.to_ident() + ), + labels: vec![(span, "".into())], + notes: vec![format!( + concat!( + "Let Naga maintainers know that you ran into this at ", + ", ", + "so they can prioritize it!" + ), + triggering_rule.tracking_issue_num() + )], + }, } } } diff --git a/naga/src/front/wgsl/parse/directive.rs b/naga/src/front/wgsl/parse/directive.rs index 49a3cdde41..5302fff138 100644 --- a/naga/src/front/wgsl/parse/directive.rs +++ b/naga/src/front/wgsl/parse/directive.rs @@ -7,12 +7,14 @@ pub(crate) mod language_extension; /// A parsed sentinel word indicating the type of directive to be parsed next. #[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[cfg_attr(test, derive(strum::EnumIter))] pub(crate) enum DirectiveKind { + /// A [`crate::diagnostic_filter`]. + Diagnostic, /// An [`enable_extension`]. Enable, /// A [`language_extension`]. Requires, - Unimplemented(UnimplementedDirectiveKind), } impl DirectiveKind { @@ -23,44 +25,25 @@ impl DirectiveKind { /// Convert from a sentinel word in WGSL into its associated [`DirectiveKind`], if possible. pub fn from_ident(s: &str) -> Option { Some(match s { - Self::DIAGNOSTIC => Self::Unimplemented(UnimplementedDirectiveKind::Diagnostic), + Self::DIAGNOSTIC => Self::Diagnostic, Self::ENABLE => Self::Enable, Self::REQUIRES => Self::Requires, _ => return None, }) } - - /// Maps this [`DirectiveKind`] into the sentinel word associated with it in WGSL. - pub const fn to_ident(self) -> &'static str { - match self { - Self::Enable => Self::ENABLE, - Self::Requires => Self::REQUIRES, - Self::Unimplemented(kind) => match kind { - UnimplementedDirectiveKind::Diagnostic => Self::DIAGNOSTIC, - }, - } - } - - #[cfg(test)] - fn iter() -> impl Iterator { - use strum::IntoEnumIterator; - - UnimplementedDirectiveKind::iter().map(Self::Unimplemented) - } } -/// A [`DirectiveKind`] that is not yet implemented. See [`DirectiveKind::Unimplemented`]. -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] -#[cfg_attr(test, derive(strum::EnumIter))] -pub(crate) enum UnimplementedDirectiveKind { - Diagnostic, -} - -impl UnimplementedDirectiveKind { - pub const fn tracking_issue_num(self) -> u16 { - match self { - Self::Diagnostic => 5320, - } +impl crate::diagnostic_filter::Severity { + #[cfg(feature = "wgsl-in")] + pub(crate) fn report_wgsl_parse_diag<'a>( + self, + err: crate::front::wgsl::error::Error<'a>, + source: &str, + ) -> Result<(), crate::front::wgsl::error::Error<'a>> { + self.report_diag(err, |e, level| { + let e = e.as_parse_error(source); + log::log!(level, "{}", e.emit_to_string(source)); + }) } } @@ -70,32 +53,7 @@ mod test { use crate::front::wgsl::assert_parse_err; - use super::{DirectiveKind, UnimplementedDirectiveKind}; - - #[test] - fn unimplemented_directives() { - for unsupported_shader in UnimplementedDirectiveKind::iter() { - let shader; - let expected_msg; - match unsupported_shader { - UnimplementedDirectiveKind::Diagnostic => { - shader = "diagnostic(off,derivative_uniformity);"; - expected_msg = "\ -error: the `diagnostic` directive is not yet implemented - ┌─ wgsl:1:1 - │ -1 │ diagnostic(off,derivative_uniformity); - │ ^^^^^^^^^^ this global directive is standard, but not yet implemented - │ - = note: Let Naga maintainers know that you ran into this at , so they can prioritize it! - -"; - } - }; - - assert_parse_err(shader, expected_msg); - } - } + use super::DirectiveKind; #[test] fn directive_after_global_decl() { @@ -103,7 +61,7 @@ error: the `diagnostic` directive is not yet implemented let directive; let expected_msg; match unsupported_shader { - DirectiveKind::Unimplemented(UnimplementedDirectiveKind::Diagnostic) => { + DirectiveKind::Diagnostic => { directive = "diagnostic(off,derivative_uniformity)"; expected_msg = "\ error: expected global declaration, but found a global directive diff --git a/naga/src/front/wgsl/parse/mod.rs b/naga/src/front/wgsl/parse/mod.rs index fcfcc37750..4e674062b1 100644 --- a/naga/src/front/wgsl/parse/mod.rs +++ b/naga/src/front/wgsl/parse/mod.rs @@ -1,3 +1,4 @@ +use crate::diagnostic_filter::{self, DiagnosticFilter, FilterableTriggeringRule}; use crate::front::wgsl::error::{Error, ExpectedToken}; use crate::front::wgsl::parse::directive::enable_extension::{ EnableExtension, EnableExtensions, UnimplementedEnableExtension, @@ -2524,11 +2525,22 @@ impl Parser { let mut enable_extensions = EnableExtensions::empty(); // Parse directives. - while let Ok((ident, span)) = lexer.peek_ident_with_span() { + while let Ok((ident, _directive_ident_span)) = lexer.peek_ident_with_span() { if let Some(kind) = DirectiveKind::from_ident(ident) { self.push_rule_span(Rule::Directive, &mut lexer); let _ = lexer.next_ident_with_span().unwrap(); match kind { + DirectiveKind::Diagnostic => { + if let Some(diagnostic_filter) = self.diagnostic_filter(&mut lexer)? { + let triggering_rule = diagnostic_filter.triggering_rule; + let span = self.peek_rule_span(&lexer); + Err(Error::DiagnosticNotYetImplemented { + triggering_rule, + span, + })?; + } + lexer.expect(Token::Separator(';'))?; + } DirectiveKind::Enable => { self.directive_ident_list(&mut lexer, |ident, span| { let kind = EnableExtension::from_ident(ident, span)?; @@ -2562,9 +2574,6 @@ impl Parser { } })?; } - DirectiveKind::Unimplemented(kind) => { - return Err(Error::DirectiveNotYetImplemented { kind, span }) - } } self.pop_rule_span(&lexer); } else { @@ -2614,4 +2623,55 @@ impl Parser { } Ok(brace_nesting_level + 1) } + + fn diagnostic_filter<'a>( + &self, + lexer: &mut Lexer<'a>, + ) -> Result, Error<'a>> { + lexer.expect(Token::Paren('('))?; + + let (severity_control_name, severity_control_name_span) = lexer.next_ident_with_span()?; + let new_severity = diagnostic_filter::Severity::from_ident(severity_control_name).ok_or( + Error::DiagnosticInvalidSeverity { + severity_control_name_span, + }, + )?; + + lexer.expect(Token::Separator(','))?; + + let (diagnostic_name_token, diagnostic_name_token_span) = lexer.next_ident_with_span()?; + let diagnostic_rule_name = if lexer.skip(Token::Separator('.')) { + // Don't try to validate these name tokens on two tokens, which is conventionally used + // for third-party tooling. + lexer.next_ident_with_span()?; + None + } else { + Some(diagnostic_name_token) + }; + let diagnostic_rule_name_span = diagnostic_name_token_span; + + let filter = diagnostic_rule_name + .and_then(|name| { + FilterableTriggeringRule::from_ident(name) + .map(Ok) + .or_else(|| { + diagnostic_filter::Severity::Warning + .report_wgsl_parse_diag( + Error::UnknownDiagnosticRuleName(diagnostic_rule_name_span), + lexer.source, + ) + .err() + .map(Err) + }) + }) + .transpose()? + .map(|triggering_rule| DiagnosticFilter { + new_severity, + triggering_rule, + }); + lexer.skip(Token::Separator(',')); + lexer.expect(Token::Paren(')'))?; + + Ok(filter) + } } diff --git a/naga/src/lib.rs b/naga/src/lib.rs index 8e373b45d6..ba8678c7a2 100644 --- a/naga/src/lib.rs +++ b/naga/src/lib.rs @@ -255,6 +255,7 @@ pub mod back; mod block; #[cfg(feature = "compact")] pub mod compact; +pub mod diagnostic_filter; pub mod error; pub mod front; pub mod keywords; diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index 60b4165a42..5906aeb339 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wgpu-core" -version = "22.0.0" +version = "23.0.0" authors = ["gfx-rs developers"] edition = "2021" description = "WebGPU core logic on wgpu-hal" @@ -129,17 +129,17 @@ thiserror.workspace = true [dependencies.naga] path = "../naga" -version = "22.0.0" +version = "23.0.0" [dependencies.wgt] package = "wgpu-types" path = "../wgpu-types" -version = "22.0.0" +version = "23.0.0" [dependencies.hal] package = "wgpu-hal" path = "../wgpu-hal" -version = "22.0.0" +version = "23.0.0" default-features = false [build-dependencies] diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 418bd5cee1..35e85f45da 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wgpu-hal" -version = "22.0.0" +version = "23.0.0" authors = ["gfx-rs developers"] edition = "2021" description = "WebGPU hardware abstraction layer" @@ -133,7 +133,7 @@ glow = { workspace = true, optional = true } [dependencies.wgt] package = "wgpu-types" path = "../wgpu-types" -version = "22.0.0" +version = "23.0.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # backend: Vulkan @@ -191,7 +191,7 @@ ndk-sys = { workspace = true, optional = true } [dependencies.naga] path = "../naga" -version = "22.0.0" +version = "23.0.0" [build-dependencies] cfg_aliases.workspace = true @@ -199,7 +199,7 @@ cfg_aliases.workspace = true # DEV dependencies [dev-dependencies.naga] path = "../naga" -version = "22.0.0" +version = "23.0.0" features = ["wgsl-in"] [dev-dependencies] diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 6578252c1a..0cddb69976 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -305,24 +305,28 @@ pub type AtomicFenceValue = std::sync::atomic::AtomicU64; /// A callback to signal that wgpu is no longer using a resource. #[cfg(any(gles, vulkan))] -pub type DropCallback = Box; +pub type DropCallback = Box; #[cfg(any(gles, vulkan))] pub struct DropGuard { - callback: DropCallback, + callback: Option, } #[cfg(all(any(gles, vulkan), any(native, Emscripten)))] impl DropGuard { fn from_option(callback: Option) -> Option { - callback.map(|callback| Self { callback }) + callback.map(|callback| Self { + callback: Some(callback), + }) } } #[cfg(any(gles, vulkan))] impl Drop for DropGuard { fn drop(&mut self) { - (self.callback)(); + if let Some(cb) = self.callback.take() { + (cb)(); + } } } diff --git a/wgpu-types/Cargo.toml b/wgpu-types/Cargo.toml index 38bda98bc2..e79ae330e5 100644 --- a/wgpu-types/Cargo.toml +++ b/wgpu-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wgpu-types" -version = "22.0.0" +version = "23.0.0" authors = ["gfx-rs developers"] edition = "2021" description = "WebGPU types"