From 43f51d68e0886570047770c5a9f1baa778727438 Mon Sep 17 00:00:00 2001 From: Vecvec Date: Mon, 17 Nov 2025 18:07:33 +1300 Subject: [PATCH 1/3] Add enable extensions for ray queries and ray query vertex returns. --- .../features/src/ray_cube_compute/shader.wgsl | 1 + .../src/ray_cube_fragment/shader.wgsl | 2 + .../features/src/ray_cube_normals/shader.wgsl | 2 + examples/features/src/ray_scene/shader.wgsl | 2 + examples/features/src/ray_shadows/shader.wgsl | 2 + .../src/ray_traced_triangle/shader.wgsl | 2 + .../wgsl/parse/directive/enable_extension.rs | 26 +++++++ naga/src/front/wgsl/parse/mod.rs | 76 ++++++++++++++++++- naga/tests/in/wgsl/aliased-ray-query.wgsl | 2 + naga/tests/in/wgsl/overrides-ray-query.wgsl | 2 + .../in/wgsl/ray-query-no-init-tracking.wgsl | 2 + naga/tests/in/wgsl/ray-query.wgsl | 2 + tests/tests/wgpu-gpu/ray_tracing/shader.wgsl | 2 + .../examples/ray-traced-triangle/shader.wgsl | 2 + 14 files changed, 123 insertions(+), 2 deletions(-) diff --git a/examples/features/src/ray_cube_compute/shader.wgsl b/examples/features/src/ray_cube_compute/shader.wgsl index cba6e1f8488..8a4e64ef1c8 100644 --- a/examples/features/src/ray_cube_compute/shader.wgsl +++ b/examples/features/src/ray_cube_compute/shader.wgsl @@ -40,6 +40,7 @@ struct RayIntersection { world_to_object: mat4x3, } */ +enable wgpu_ray_query; struct Uniforms { view_inv: mat4x4, diff --git a/examples/features/src/ray_cube_fragment/shader.wgsl b/examples/features/src/ray_cube_fragment/shader.wgsl index d98faeb0116..bb2ddb65e21 100644 --- a/examples/features/src/ray_cube_fragment/shader.wgsl +++ b/examples/features/src/ray_cube_fragment/shader.wgsl @@ -1,3 +1,5 @@ +enable wgpu_ray_query; + struct VertexOutput { @builtin(position) position: vec4, @location(0) tex_coords: vec2, diff --git a/examples/features/src/ray_cube_normals/shader.wgsl b/examples/features/src/ray_cube_normals/shader.wgsl index 93b69834e0e..35c3898e70c 100644 --- a/examples/features/src/ray_cube_normals/shader.wgsl +++ b/examples/features/src/ray_cube_normals/shader.wgsl @@ -39,6 +39,8 @@ struct RayIntersection { world_to_object: mat4x3, } */ +enable wgpu_ray_query; +enable wgpu_ray_query_vertex_return; struct Uniforms { view_inv: mat4x4, diff --git a/examples/features/src/ray_scene/shader.wgsl b/examples/features/src/ray_scene/shader.wgsl index 496125ea5cd..c7e75d5117a 100644 --- a/examples/features/src/ray_scene/shader.wgsl +++ b/examples/features/src/ray_scene/shader.wgsl @@ -1,3 +1,5 @@ +enable wgpu_ray_query; + struct VertexOutput { @builtin(position) position: vec4, @location(0) tex_coords: vec2, diff --git a/examples/features/src/ray_shadows/shader.wgsl b/examples/features/src/ray_shadows/shader.wgsl index 4ba5d42f795..8ce3c0d64cf 100644 --- a/examples/features/src/ray_shadows/shader.wgsl +++ b/examples/features/src/ray_shadows/shader.wgsl @@ -1,3 +1,5 @@ +enable wgpu_ray_query; + struct VertexOutput { @builtin(position) position: vec4, @location(0) tex_coords: vec2, diff --git a/examples/features/src/ray_traced_triangle/shader.wgsl b/examples/features/src/ray_traced_triangle/shader.wgsl index 54b1eb54204..fafd5fac6ab 100644 --- a/examples/features/src/ray_traced_triangle/shader.wgsl +++ b/examples/features/src/ray_traced_triangle/shader.wgsl @@ -1,5 +1,7 @@ // duplicate of hal's ray-traced triangle shader +enable wgpu_ray_query; + struct Uniforms { view_inv: mat4x4, proj_inv: mat4x4, diff --git a/naga/src/front/wgsl/parse/directive/enable_extension.rs b/naga/src/front/wgsl/parse/directive/enable_extension.rs index 7d1e1b2df6e..a4ca097df8f 100644 --- a/naga/src/front/wgsl/parse/directive/enable_extension.rs +++ b/naga/src/front/wgsl/parse/directive/enable_extension.rs @@ -11,6 +11,8 @@ use alloc::boxed::Box; #[derive(Clone, Debug, Eq, PartialEq)] pub struct EnableExtensions { wgpu_mesh_shader: bool, + wgpu_ray_query: bool, + wgpu_ray_query_vertex_return: bool, dual_source_blending: bool, /// Whether `enable f16;` was written earlier in the shader module. f16: bool, @@ -21,6 +23,8 @@ impl EnableExtensions { pub(crate) const fn empty() -> Self { Self { wgpu_mesh_shader: false, + wgpu_ray_query: false, + wgpu_ray_query_vertex_return: false, f16: false, dual_source_blending: false, clip_distances: false, @@ -31,6 +35,10 @@ impl EnableExtensions { pub(crate) fn add(&mut self, ext: ImplementedEnableExtension) { let field = match ext { ImplementedEnableExtension::WgpuMeshShader => &mut self.wgpu_mesh_shader, + ImplementedEnableExtension::WgpuRayQuery => &mut self.wgpu_ray_query, + ImplementedEnableExtension::WgpuRayQueryVertexReturn => { + &mut self.wgpu_ray_query_vertex_return + } ImplementedEnableExtension::DualSourceBlending => &mut self.dual_source_blending, ImplementedEnableExtension::F16 => &mut self.f16, ImplementedEnableExtension::ClipDistances => &mut self.clip_distances, @@ -42,6 +50,10 @@ impl EnableExtensions { pub(crate) const fn contains(&self, ext: ImplementedEnableExtension) -> bool { match ext { ImplementedEnableExtension::WgpuMeshShader => self.wgpu_mesh_shader, + ImplementedEnableExtension::WgpuRayQuery => self.wgpu_ray_query, + ImplementedEnableExtension::WgpuRayQueryVertexReturn => { + self.wgpu_ray_query_vertex_return + } ImplementedEnableExtension::DualSourceBlending => self.dual_source_blending, ImplementedEnableExtension::F16 => self.f16, ImplementedEnableExtension::ClipDistances => self.clip_distances, @@ -75,6 +87,8 @@ impl EnableExtension { const CLIP_DISTANCES: &'static str = "clip_distances"; const DUAL_SOURCE_BLENDING: &'static str = "dual_source_blending"; const MESH_SHADER: &'static str = "wgpu_mesh_shader"; + const RAY_QUERY: &'static str = "wgpu_ray_query"; + const RAY_QUERY_VERTEX_RETURN: &'static str = "wgpu_ray_query_vertex_return"; const SUBGROUPS: &'static str = "subgroups"; const PRIMITIVE_INDEX: &'static str = "primitive_index"; @@ -87,6 +101,10 @@ impl EnableExtension { Self::Implemented(ImplementedEnableExtension::DualSourceBlending) } Self::MESH_SHADER => Self::Implemented(ImplementedEnableExtension::WgpuMeshShader), + Self::RAY_QUERY => Self::Implemented(ImplementedEnableExtension::WgpuRayQuery), + Self::RAY_QUERY_VERTEX_RETURN => { + Self::Implemented(ImplementedEnableExtension::WgpuRayQueryVertexReturn) + } Self::SUBGROUPS => Self::Unimplemented(UnimplementedEnableExtension::Subgroups), Self::PRIMITIVE_INDEX => { Self::Unimplemented(UnimplementedEnableExtension::PrimitiveIndex) @@ -100,6 +118,10 @@ impl EnableExtension { match self { Self::Implemented(kind) => match kind { ImplementedEnableExtension::WgpuMeshShader => Self::MESH_SHADER, + ImplementedEnableExtension::WgpuRayQuery => Self::RAY_QUERY, + ImplementedEnableExtension::WgpuRayQueryVertexReturn => { + Self::RAY_QUERY_VERTEX_RETURN + } ImplementedEnableExtension::DualSourceBlending => Self::DUAL_SOURCE_BLENDING, ImplementedEnableExtension::F16 => Self::F16, ImplementedEnableExtension::ClipDistances => Self::CLIP_DISTANCES, @@ -135,6 +157,10 @@ pub enum ImplementedEnableExtension { ClipDistances, /// Enables the `wgpu_mesh_shader` extension, native only WgpuMeshShader, + /// Enables the `wgpu_ray_query` extension, native only. + WgpuRayQuery, + /// Enables the `wgpu_ray_query_vertex_return` extension, native only. + WgpuRayQueryVertexReturn, } /// A variant of [`EnableExtension::Unimplemented`]. diff --git a/naga/src/front/wgsl/parse/mod.rs b/naga/src/front/wgsl/parse/mod.rs index 838a4dd1a88..142606b83e1 100644 --- a/naga/src/front/wgsl/parse/mod.rs +++ b/naga/src/front/wgsl/parse/mod.rs @@ -1930,15 +1930,87 @@ impl Parser { } } "acceleration_structure" => { + if !lexer + .enable_extensions + .contains(ImplementedEnableExtension::WgpuRayQuery) + { + return Err(Box::new(Error::EnableExtensionNotEnabled { + kind: EnableExtension::Implemented( + ImplementedEnableExtension::WgpuRayQuery, + ), + span, + })); + } let vertex_return = lexer.next_acceleration_structure_flags()?; + if !lexer + .enable_extensions + .contains(ImplementedEnableExtension::WgpuRayQueryVertexReturn) + && vertex_return + { + return Err(Box::new(Error::EnableExtensionNotEnabled { + kind: EnableExtension::Implemented( + ImplementedEnableExtension::WgpuRayQueryVertexReturn, + ), + span, + })); + } ast::Type::AccelerationStructure { vertex_return } } "ray_query" => { + if !lexer + .enable_extensions + .contains(ImplementedEnableExtension::WgpuRayQuery) + { + return Err(Box::new(Error::EnableExtensionNotEnabled { + kind: EnableExtension::Implemented( + ImplementedEnableExtension::WgpuRayQuery, + ), + span, + })); + } let vertex_return = lexer.next_acceleration_structure_flags()?; + if !lexer + .enable_extensions + .contains(ImplementedEnableExtension::WgpuRayQueryVertexReturn) + && vertex_return + { + return Err(Box::new(Error::EnableExtensionNotEnabled { + kind: EnableExtension::Implemented( + ImplementedEnableExtension::WgpuRayQueryVertexReturn, + ), + span, + })); + } ast::Type::RayQuery { vertex_return } } - "RayDesc" => ast::Type::RayDesc, - "RayIntersection" => ast::Type::RayIntersection, + "RayDesc" => { + if !lexer + .enable_extensions + .contains(ImplementedEnableExtension::WgpuRayQuery) + { + return Err(Box::new(Error::EnableExtensionNotEnabled { + kind: EnableExtension::Implemented( + ImplementedEnableExtension::WgpuRayQuery, + ), + span, + })); + } + ast::Type::RayDesc + } + "RayIntersection" => { + if !lexer + .enable_extensions + .contains(ImplementedEnableExtension::WgpuRayQuery) + { + return Err(Box::new(Error::EnableExtensionNotEnabled { + kind: EnableExtension::Implemented( + ImplementedEnableExtension::WgpuRayQuery, + ), + span, + })); + } + ast::Type::RayIntersection + } _ => return Ok(None), })) } diff --git a/naga/tests/in/wgsl/aliased-ray-query.wgsl b/naga/tests/in/wgsl/aliased-ray-query.wgsl index d56d5be1e45..6650a071208 100644 --- a/naga/tests/in/wgsl/aliased-ray-query.wgsl +++ b/naga/tests/in/wgsl/aliased-ray-query.wgsl @@ -1,3 +1,5 @@ +enable wgpu_ray_query; + alias rq = ray_query; @group(0) @binding(0) diff --git a/naga/tests/in/wgsl/overrides-ray-query.wgsl b/naga/tests/in/wgsl/overrides-ray-query.wgsl index dca7447ed0b..c5342e7eafe 100644 --- a/naga/tests/in/wgsl/overrides-ray-query.wgsl +++ b/naga/tests/in/wgsl/overrides-ray-query.wgsl @@ -1,3 +1,5 @@ +enable wgpu_ray_query; + override o: f32; @group(0) @binding(0) diff --git a/naga/tests/in/wgsl/ray-query-no-init-tracking.wgsl b/naga/tests/in/wgsl/ray-query-no-init-tracking.wgsl index e8fabb0208c..22734515f85 100644 --- a/naga/tests/in/wgsl/ray-query-no-init-tracking.wgsl +++ b/naga/tests/in/wgsl/ray-query-no-init-tracking.wgsl @@ -40,6 +40,8 @@ struct RayIntersection { } */ +enable wgpu_ray_query; + fn query_loop(pos: vec3, dir: vec3, acs: acceleration_structure) -> RayIntersection { var rq: ray_query; rayQueryInitialize(&rq, acs, RayDesc(RAY_FLAG_TERMINATE_ON_FIRST_HIT, 0xFFu, 0.1, 100.0, pos, dir)); diff --git a/naga/tests/in/wgsl/ray-query.wgsl b/naga/tests/in/wgsl/ray-query.wgsl index e8fabb0208c..22734515f85 100644 --- a/naga/tests/in/wgsl/ray-query.wgsl +++ b/naga/tests/in/wgsl/ray-query.wgsl @@ -40,6 +40,8 @@ struct RayIntersection { } */ +enable wgpu_ray_query; + fn query_loop(pos: vec3, dir: vec3, acs: acceleration_structure) -> RayIntersection { var rq: ray_query; rayQueryInitialize(&rq, acs, RayDesc(RAY_FLAG_TERMINATE_ON_FIRST_HIT, 0xFFu, 0.1, 100.0, pos, dir)); diff --git a/tests/tests/wgpu-gpu/ray_tracing/shader.wgsl b/tests/tests/wgpu-gpu/ray_tracing/shader.wgsl index 55a8f4b85d6..2ed0aac3b6b 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/shader.wgsl +++ b/tests/tests/wgpu-gpu/ray_tracing/shader.wgsl @@ -1,3 +1,5 @@ +enable wgpu_ray_query; + @group(0) @binding(0) var acc_struct: acceleration_structure; diff --git a/wgpu-hal/examples/ray-traced-triangle/shader.wgsl b/wgpu-hal/examples/ray-traced-triangle/shader.wgsl index 8d9e475e3ee..9710ca65fcd 100644 --- a/wgpu-hal/examples/ray-traced-triangle/shader.wgsl +++ b/wgpu-hal/examples/ray-traced-triangle/shader.wgsl @@ -1,3 +1,5 @@ +enable wgpu_ray_query; + struct Uniforms { view_inv: mat4x4, proj_inv: mat4x4, From 3c56eb23bc50d610ba288f84e574265258fe931a Mon Sep 17 00:00:00 2001 From: Vecvec Date: Wed, 19 Nov 2025 08:08:03 +1300 Subject: [PATCH 2/3] Changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9643107bd8a..3b9c50c1b97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,6 +115,7 @@ By @SupaMaggie70Incorporated in [#8206](https://github.com/gfx-rs/wgpu/pull/8206 #### General +- Require new enable extensions when using ray queries and position fetch (`wgpu_ray_query`, `wgpu_ray_query_vertex_return`). By @Vecvec in [#8545](https://github.com/gfx-rs/wgpu/pull/8545). - Lower `max_blas_primitive_count` due to a bug in llvmpipe. By @Vecvec in [#8446](https://github.com/gfx-rs/wgpu/pull/8446). - Texture now has `from_custom`. By @R-Cramer4 in [#8315](https://github.com/gfx-rs/wgpu/pull/8315). - Using both the wgpu command encoding APIs and `CommandEncoder::as_hal_mut` on the same encoder will now result in a panic. From 72457016224d02220b26d578ba1a4847292af23c Mon Sep 17 00:00:00 2001 From: Vecvec Date: Wed, 19 Nov 2025 09:00:41 +1300 Subject: [PATCH 3/3] error tests --- naga/src/valid/mod.rs | 2 + naga/tests/naga/wgsl_errors.rs | 96 ++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/naga/src/valid/mod.rs b/naga/src/valid/mod.rs index 0ec5c5184f2..8dcea0acffc 100644 --- a/naga/src/valid/mod.rs +++ b/naga/src/valid/mod.rs @@ -208,6 +208,8 @@ impl Capabilities { // NOTE: `SHADER_FLOAT16_IN_FLOAT32` _does not_ require the `f16` extension Self::SHADER_FLOAT16 => Some(Ext::F16), Self::CLIP_DISTANCE => Some(Ext::ClipDistances), + Self::RAY_QUERY => Some(Ext::WgpuRayQuery), + Self::RAY_HIT_VERTEX_POSITION => Some(Ext::WgpuRayQueryVertexReturn), _ => None, } } diff --git a/naga/tests/naga/wgsl_errors.rs b/naga/tests/naga/wgsl_errors.rs index 675f52b94e1..c9c41328408 100644 --- a/naga/tests/naga/wgsl_errors.rs +++ b/naga/tests/naga/wgsl_errors.rs @@ -4283,3 +4283,99 @@ fn source_with_control_char() { ", ); } + +#[test] +fn ray_query_enable_extension() { + check_extension_validation!( + Capabilities::RAY_QUERY, + r#"fn foo() { + var a: ray_query; + } + "#, + r#"error: the `wgpu_ray_query` enable extension is not enabled + ┌─ wgsl:2:20 + │ +2 │ var a: ray_query; + │ ^^^^^^^^^ the `wgpu_ray_query` "Enable Extension" is needed for this functionality, but it is not currently enabled. + │ + = note: You can enable this extension by adding `enable wgpu_ray_query;` at the top of the shader, before any other items. + +"#, + Err(naga::valid::ValidationError::Type { + source: naga::valid::TypeError::MissingCapability(Capabilities::RAY_QUERY), + .. + }) + ); + + check_extension_validation!( + Capabilities::RAY_QUERY, + r#"@group(0) @binding(0) + var acc_struct: acceleration_structure; + "#, + r#"error: the `wgpu_ray_query` enable extension is not enabled + ┌─ wgsl:2:25 + │ +2 │ var acc_struct: acceleration_structure; + │ ^^^^^^^^^^^^^^^^^^^^^^ the `wgpu_ray_query` "Enable Extension" is needed for this functionality, but it is not currently enabled. + │ + = note: You can enable this extension by adding `enable wgpu_ray_query;` at the top of the shader, before any other items. + +"#, + Err(naga::valid::ValidationError::Type { + source: naga::valid::TypeError::MissingCapability(Capabilities::RAY_QUERY), + .. + }) + ); +} + +#[test] +fn ray_query_vertex_return_enable_extension() { + check_extension_validation!( + Capabilities::RAY_HIT_VERTEX_POSITION, + r#"enable wgpu_ray_query; + + fn foo() { + var a: ray_query; + } + "#, + r#"error: the `wgpu_ray_query_vertex_return` enable extension is not enabled + ┌─ wgsl:4:20 + │ +4 │ var a: ray_query; + │ ^^^^^^^^^ the `wgpu_ray_query_vertex_return` "Enable Extension" is needed for this functionality, but it is not currently enabled. + │ + = note: You can enable this extension by adding `enable wgpu_ray_query_vertex_return;` at the top of the shader, before any other items. + +"#, + Err(naga::valid::ValidationError::Type { + source: naga::valid::TypeError::MissingCapability( + Capabilities::RAY_HIT_VERTEX_POSITION + ), + .. + }) + ); + + check_extension_validation!( + Capabilities::RAY_HIT_VERTEX_POSITION, + r#"enable wgpu_ray_query; + + @group(0) @binding(0) + var acc_struct: acceleration_structure; + "#, + r#"error: the `wgpu_ray_query_vertex_return` enable extension is not enabled + ┌─ wgsl:4:25 + │ +4 │ var acc_struct: acceleration_structure; + │ ^^^^^^^^^^^^^^^^^^^^^^ the `wgpu_ray_query_vertex_return` "Enable Extension" is needed for this functionality, but it is not currently enabled. + │ + = note: You can enable this extension by adding `enable wgpu_ray_query_vertex_return;` at the top of the shader, before any other items. + +"#, + Err(naga::valid::ValidationError::Type { + source: naga::valid::TypeError::MissingCapability( + Capabilities::RAY_HIT_VERTEX_POSITION + ), + .. + }) + ); +}