Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose all ray-query flags in constants #5429

Merged
merged 3 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ By @ErichDonGubler in [#6456](https://github.com/gfx-rs/wgpu/pull/6456), [#6148]
- Fix textureNumLevels in the GLSL backend. By @magcius in [#6483](https://github.com/gfx-rs/wgpu/pull/6483).
- Implement `quantizeToF16()` for WGSL frontend, and WGSL, SPIR-V, HLSL, MSL, and GLSL backends. By @jamienicol in [#6519](https://github.com/gfx-rs/wgpu/pull/6519).
- Add support for GLSL `usampler*` and `isampler*`. By @DavidPeicho in [#6513](https://github.com/gfx-rs/wgpu/pull/6513).
- Expose Ray Query flags as constants in WGSL. Implement candidate intersections. By @kvark in [#5429](https://github.com/gfx-rs/wgpu/pull/5429)

#### General

Expand Down Expand Up @@ -128,7 +129,7 @@ By @ErichDonGubler in [#6456](https://github.com/gfx-rs/wgpu/pull/6456), [#6148]

- Handle query set creation failure as an internal error that loses the `Device`, rather than panicking. By @ErichDonGubler in [#6505](https://github.com/gfx-rs/wgpu/pull/6505).
- Ensure that `Features::TIMESTAMP_QUERY` is set when using timestamp writes in render and compute passes. By @ErichDonGubler in [#6497](https://github.com/gfx-rs/wgpu/pull/6497).
- Check for device mismatches when beginning render and compute passes. By @ErichDonGubler in [#6497](https://github.com/gfx-rs/wgpu/pull/6497).
- Check for device mismatches when beginning render and compute passes. By @ErichDonGubler in [#6497](https://github.com/gfx-rs/wgpu/pull/6497).
- Lower `QUERY_SET_MAX_QUERIES` (and enforced limits) from 8192 to 4096 to match WebGPU spec. By @ErichDonGubler in [#6525](https://github.com/gfx-rs/wgpu/pull/6525).
- Allow non-filterable float on texture bindings never used with samplers when using a derived bind group layout. By @ErichDonGubler in [#6531](https://github.com/gfx-rs/wgpu/pull/6531/).
- Replace potentially unsound usage of `PreHashedMap` with `FastHashMap`. By @jamienicol in [#6541](https://github.com/gfx-rs/wgpu/pull/6541).
Expand Down
3 changes: 1 addition & 2 deletions examples/src/ray_cube_compute/shader.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let RAY_FLAG_SKIP_AABBS = 0x200u;
let RAY_QUERY_INTERSECTION_NONE = 0u;
let RAY_QUERY_INTERSECTION_TRIANGLE = 1u;
let RAY_QUERY_INTERSECTION_GENERATED = 2u;
let RAY_QUERY_INTERSECTION_AABB = 4u;
let RAY_QUERY_INTERSECTION_AABB = 3u;

struct RayDesc {
flags: u32,
Expand Down Expand Up @@ -60,7 +60,6 @@ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
let target_size = textureDimensions(output);
var color = vec4<f32>(vec2<f32>(global_id.xy) / vec2<f32>(target_size), 0.0, 1.0);


let pixel_center = vec2<f32>(global_id.xy) + vec2<f32>(0.5);
let in_uv = pixel_center/vec2<f32>(target_size.xy);
let d = in_uv * 2.0 - 1.0;
Expand Down
2 changes: 1 addition & 1 deletion examples/src/ray_scene/shader.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ let RAY_FLAG_SKIP_AABBS = 0x200u;
let RAY_QUERY_INTERSECTION_NONE = 0u;
let RAY_QUERY_INTERSECTION_TRIANGLE = 1u;
let RAY_QUERY_INTERSECTION_GENERATED = 2u;
let RAY_QUERY_INTERSECTION_AABB = 4u;
let RAY_QUERY_INTERSECTION_AABB = 3u;

struct RayDesc {
flags: u32,
Expand Down
8 changes: 4 additions & 4 deletions naga/src/back/msl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2254,14 +2254,14 @@ impl<W: Write> Writer<W> {
write!(self.out, ")")?;
}
}
crate::Expression::RayQueryGetIntersection { query, committed } => {
crate::Expression::RayQueryGetIntersection {
query,
committed: _,
} => {
if context.lang_version < (2, 4) {
return Err(Error::UnsupportedRayTracing);
}

if !committed {
unimplemented!()
}
let ty = context.module.special_types.ray_intersection.unwrap();
let type_name = &self.names[&NameKey::Type(ty)];
write!(self.out, "{type_name} {{{RAY_QUERY_FUN_MAP_INTERSECTION}(")?;
Expand Down
5 changes: 1 addition & 4 deletions naga/src/back/spv/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1736,10 +1736,7 @@ impl<'w> BlockContext<'w> {
}
crate::Expression::ArrayLength(expr) => self.write_runtime_array_length(expr, block)?,
crate::Expression::RayQueryGetIntersection { query, committed } => {
if !committed {
return Err(Error::FeatureNotImplemented("candidate intersection"));
}
self.write_ray_query_get_intersection(query, block)
self.write_ray_query_get_intersection(query, block, committed)
}
};

Expand Down
49 changes: 44 additions & 5 deletions naga/src/back/spv/ray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,23 +106,60 @@ impl<'w> BlockContext<'w> {
&mut self,
query: Handle<crate::Expression>,
block: &mut Block,
is_committed: bool,
) -> spirv::Word {
let query_id = self.cached[query];
let intersection_id = self.writer.get_constant_scalar(crate::Literal::U32(
spirv::RayQueryIntersection::RayQueryCommittedIntersectionKHR as _,
));
let intersection_id =
self.writer
.get_constant_scalar(crate::Literal::U32(if is_committed {
spirv::RayQueryIntersection::RayQueryCommittedIntersectionKHR
} else {
spirv::RayQueryIntersection::RayQueryCandidateIntersectionKHR
} as _));

let flag_type_id = self.get_type_id(LookupType::Local(LocalType::Numeric(
NumericType::Scalar(crate::Scalar::U32),
)));
let kind_id = self.gen_id();
let raw_kind_id = self.gen_id();
block.body.push(Instruction::ray_query_get_intersection(
spirv::Op::RayQueryGetIntersectionTypeKHR,
flag_type_id,
kind_id,
raw_kind_id,
query_id,
intersection_id,
));
let kind_id = if is_committed {
// Nothing to do: the IR value matches `spirv::RayQueryCommittedIntersectionType`
raw_kind_id
} else {
// Remap from the candidate kind to IR
let condition_id = self.gen_id();
let committed_triangle_kind_id = self.writer.get_constant_scalar(crate::Literal::U32(
spirv::RayQueryCandidateIntersectionType::RayQueryCandidateIntersectionTriangleKHR
as _,
));
block.body.push(Instruction::binary(
spirv::Op::IEqual,
self.writer.get_bool_type_id(),
condition_id,
raw_kind_id,
committed_triangle_kind_id,
));
let kind_id = self.gen_id();
block.body.push(Instruction::select(
flag_type_id,
kind_id,
condition_id,
self.writer.get_constant_scalar(crate::Literal::U32(
crate::RayQueryIntersection::Triangle as _,
)),
self.writer.get_constant_scalar(crate::Literal::U32(
crate::RayQueryIntersection::Aabb as _,
)),
));
kind_id
};

let instance_custom_index_id = self.gen_id();
block.body.push(Instruction::ray_query_get_intersection(
spirv::Op::RayQueryGetIntersectionInstanceCustomIndexKHR,
Expand Down Expand Up @@ -201,6 +238,8 @@ impl<'w> BlockContext<'w> {
query_id,
intersection_id,
));
//Note: there is also `OpRayQueryGetIntersectionCandidateAABBOpaqueKHR`,
// but it's not a property of an intersection.

let transform_type_id =
self.get_type_id(LookupType::Local(LocalType::Numeric(NumericType::Matrix {
Expand Down
12 changes: 11 additions & 1 deletion naga/src/front/wgsl/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2568,12 +2568,22 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
args.finish()?;

let _ = ctx.module.generate_ray_intersection_type();

crate::Expression::RayQueryGetIntersection {
query,
committed: true,
}
}
"rayQueryGetCandidateIntersection" => {
let mut args = ctx.prepare_args(arguments, 1, span);
let query = self.ray_query_pointer(args.next()?, ctx)?;
args.finish()?;

let _ = ctx.module.generate_ray_intersection_type();
crate::Expression::RayQueryGetIntersection {
query,
committed: false,
}
}
"RayDesc" => {
let ty = ctx.module.generate_ray_desc_type();
let handle = self.construct(
Expand Down
62 changes: 59 additions & 3 deletions naga/src/front/wgsl/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,14 @@ impl Parser {
ctx: &mut ExpressionContext<'a, '_, '_>,
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
self.push_rule_span(Rule::PrimaryExpr, lexer);
const fn literal_ray_flag<'b>(flag: crate::RayFlag) -> ast::Expression<'b> {
ast::Expression::Literal(ast::Literal::Number(Number::U32(flag.bits())))
}
const fn literal_ray_intersection<'b>(
intersection: crate::RayQueryIntersection,
) -> ast::Expression<'b> {
ast::Expression::Literal(ast::Literal::Number(Number::U32(intersection as u32)))
}

let expr = match lexer.peek() {
(Token::Paren('('), _) => {
Expand Down Expand Up @@ -687,15 +695,63 @@ impl Parser {
}
(Token::Word("RAY_FLAG_NONE"), _) => {
let _ = lexer.next();
ast::Expression::Literal(ast::Literal::Number(Number::U32(0)))
literal_ray_flag(crate::RayFlag::empty())
}
(Token::Word("RAY_FLAG_FORCE_OPAQUE"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::FORCE_OPAQUE)
}
(Token::Word("RAY_FLAG_FORCE_NO_OPAQUE"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::FORCE_NO_OPAQUE)
}
(Token::Word("RAY_FLAG_TERMINATE_ON_FIRST_HIT"), _) => {
let _ = lexer.next();
ast::Expression::Literal(ast::Literal::Number(Number::U32(4)))
literal_ray_flag(crate::RayFlag::TERMINATE_ON_FIRST_HIT)
}
(Token::Word("RAY_FLAG_SKIP_CLOSEST_HIT_SHADER"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::SKIP_CLOSEST_HIT_SHADER)
}
(Token::Word("RAY_FLAG_CULL_BACK_FACING"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::CULL_BACK_FACING)
}
(Token::Word("RAY_FLAG_CULL_FRONT_FACING"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::CULL_FRONT_FACING)
}
(Token::Word("RAY_FLAG_CULL_OPAQUE"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::CULL_OPAQUE)
}
(Token::Word("RAY_FLAG_CULL_NO_OPAQUE"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::CULL_NO_OPAQUE)
}
(Token::Word("RAY_FLAG_SKIP_TRIANGLES"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::SKIP_TRIANGLES)
}
(Token::Word("RAY_FLAG_SKIP_AABBS"), _) => {
let _ = lexer.next();
literal_ray_flag(crate::RayFlag::SKIP_AABBS)
}
(Token::Word("RAY_QUERY_INTERSECTION_NONE"), _) => {
let _ = lexer.next();
ast::Expression::Literal(ast::Literal::Number(Number::U32(0)))
literal_ray_intersection(crate::RayQueryIntersection::None)
}
(Token::Word("RAY_QUERY_INTERSECTION_TRIANGLE"), _) => {
let _ = lexer.next();
literal_ray_intersection(crate::RayQueryIntersection::Triangle)
}
(Token::Word("RAY_QUERY_INTERSECTION_GENERATED"), _) => {
let _ = lexer.next();
literal_ray_intersection(crate::RayQueryIntersection::Generated)
}
(Token::Word("RAY_QUERY_INTERSECTION_AABB"), _) => {
let _ = lexer.next();
literal_ray_intersection(crate::RayQueryIntersection::Aabb)
}
(Token::Word(word), span) => {
let start = lexer.start_byte_offset();
Expand Down
56 changes: 56 additions & 0 deletions naga/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2295,3 +2295,59 @@ pub struct Module {
/// validation.
pub diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
}

bitflags::bitflags! {
/// Ray flags used when casting rays.
/// Matching vulkan constants can be found in
/// https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/ray_common/ray_flags_section.txt
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct RayFlag: u32 {
/// Force all intersections to be treated as opaque.
const FORCE_OPAQUE = 0x1;
/// Force all intersections to be treated as non-opaque.
const FORCE_NO_OPAQUE = 0x2;
/// Stop traversal after the first hit.
const TERMINATE_ON_FIRST_HIT = 0x4;
/// Don't execute the closest hit shader.
const SKIP_CLOSEST_HIT_SHADER = 0x8;
/// Cull back facing geometry.
const CULL_BACK_FACING = 0x10;
/// Cull front facing geometry.
const CULL_FRONT_FACING = 0x20;
/// Cull opaque geometry.
const CULL_OPAQUE = 0x40;
/// Cull non-opaque geometry.
const CULL_NO_OPAQUE = 0x80;
/// Skip triangular geometry.
const SKIP_TRIANGLES = 0x100;
/// Skip axis-aligned bounding boxes.
const SKIP_AABBS = 0x200;
}
}

/// Type of a ray query intersection.
/// Matching vulkan constants can be found in
/// <https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/SPV_KHR_ray_query.asciidoc>
/// but the actual values are different for candidate intersections.
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum RayQueryIntersection {
/// No intersection found.
/// Matches `RayQueryCommittedIntersectionNoneKHR`.
#[default]
None = 0,
/// Intersecting with triangles.
/// Matches `RayQueryCommittedIntersectionTriangleKHR` and `RayQueryCandidateIntersectionTriangleKHR`.
Triangle = 1,
/// Intersecting with generated primitives.
/// Matches `RayQueryCommittedIntersectionGeneratedKHR`.
Generated = 2,
/// Intersecting with Axis Aligned Bounding Boxes.
/// Matches `RayQueryCandidateIntersectionAABBKHR`.
Aabb = 3,
}
17 changes: 14 additions & 3 deletions naga/tests/in/ray-query.wgsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
let RAY_FLAG_NONE = 0x00u;
let RAY_FLAG_OPAQUE = 0x01u;
let RAY_FLAG_NO_OPAQUE = 0x02u;
let RAY_FLAG_FORCE_OPAQUE = 0x01u;
let RAY_FLAG_FORCE_NO_OPAQUE = 0x02u;
let RAY_FLAG_TERMINATE_ON_FIRST_HIT = 0x04u;
let RAY_FLAG_SKIP_CLOSEST_HIT_SHADER = 0x08u;
let RAY_FLAG_CULL_BACK_FACING = 0x10u;
Expand All @@ -14,7 +14,7 @@ let RAY_FLAG_SKIP_AABBS = 0x200u;
let RAY_QUERY_INTERSECTION_NONE = 0u;
let RAY_QUERY_INTERSECTION_TRIANGLE = 1u;
let RAY_QUERY_INTERSECTION_GENERATED = 2u;
let RAY_QUERY_INTERSECTION_AABB = 4u;
let RAY_QUERY_INTERSECTION_AABB = 3u;

struct RayDesc {
flags: u32,
Expand Down Expand Up @@ -78,3 +78,14 @@ fn main() {
output.visible = u32(intersection.kind == RAY_QUERY_INTERSECTION_NONE);
output.normal = get_torus_normal(dir * intersection.t, intersection);
}

@compute @workgroup_size(1)
fn main_candidate() {
let pos = vec3<f32>(0.0);
let dir = vec3<f32>(0.0, 1.0, 0.0);

var rq: ray_query;
rayQueryInitialize(&rq, acc_struct, RayDesc(RAY_FLAG_TERMINATE_ON_FIRST_HIT, 0xFFu, 0.1, 100.0, pos, dir));
let intersection = rayQueryGetCandidateIntersection(&rq);
output.visible = u32(intersection.kind == RAY_QUERY_INTERSECTION_AABB);
}
Loading