@@ -4379,3 +4379,166 @@ fn ray_query_vertex_return_enable_extension() {
43794379 } )
43804380 ) ;
43814381}
4382+
4383+ /// Checks that every ray tracing pipeline binding in naga is invalid in other stages.
4384+ #[ test]
4385+ fn check_ray_tracing_pipeline_bindings ( ) {
4386+ for ( builtin, ty) in [
4387+ ( "ray_invocation_id" , "vec3<u32>" ) ,
4388+ ( "num_ray_invocations" , "vec3<u32>" ) ,
4389+ ( "instance_custom_data" , "u32" ) ,
4390+ ( "geometry_index" , "u32" ) ,
4391+ ( "world_ray_origin" , "vec3<f32>" ) ,
4392+ ( "world_ray_direction" , "vec3<f32>" ) ,
4393+ ( "object_ray_origin" , "vec3<f32>" ) ,
4394+ ( "object_ray_direction" , "vec3<f32>" ) ,
4395+ ( "ray_t_min" , "f32" ) ,
4396+ ( "ray_t_current_max" , "f32" ) ,
4397+ ( "object_to_world" , "mat4x3<f32>" ) ,
4398+ ( "world_to_object" , "mat4x3<f32>" ) ,
4399+ ( "hit_kind" , "u32" ) ,
4400+ ] {
4401+ check_one_validation ! (
4402+ & format!(
4403+ "@compute
4404+ @workgroup_size(1)
4405+ fn main(@builtin({builtin}) v: {ty}) {{}}
4406+ "
4407+ ) ,
4408+ Err ( naga:: valid:: ValidationError :: EntryPoint {
4409+ source: naga:: valid:: EntryPointError :: Argument (
4410+ 0 ,
4411+ naga:: valid:: VaryingError :: InvalidBuiltInStage ( _) ,
4412+ ) ,
4413+ ..
4414+ } , )
4415+ ) ;
4416+ check_one_validation ! (
4417+ & format!(
4418+ "@vertex
4419+ fn main(@builtin({builtin}) v: {ty}) {{}}
4420+ "
4421+ ) ,
4422+ Err ( naga:: valid:: ValidationError :: EntryPoint {
4423+ source: naga:: valid:: EntryPointError :: Argument (
4424+ 0 ,
4425+ naga:: valid:: VaryingError :: InvalidBuiltInStage ( _) ,
4426+ ) ,
4427+ ..
4428+ } , )
4429+ ) ;
4430+ check_one_validation ! (
4431+ & format!(
4432+ "@fragment
4433+ fn main(@builtin({builtin}) v: {ty}) {{}}
4434+ "
4435+ ) ,
4436+ Err ( naga:: valid:: ValidationError :: EntryPoint {
4437+ source: naga:: valid:: EntryPointError :: Argument (
4438+ 0 ,
4439+ naga:: valid:: VaryingError :: InvalidBuiltInStage ( _) ,
4440+ ) ,
4441+ ..
4442+ } , )
4443+ ) ;
4444+ }
4445+ }
4446+
4447+ /// Checks ray generation stage is invalid without enable extension (other stages require `@incoming_payload` which forces a ray payload which is checked in [`check_ray_tracing_pipeline_payload`])
4448+ #[ test]
4449+ fn check_ray_tracing_pipeline_ray_generation ( ) {
4450+ check_extension_validation ! (
4451+ Capabilities :: RAY_TRACING_PIPELINE ,
4452+ "@ray_generation
4453+ fn main() {{}}" ,
4454+ "error: the `wgpu_ray_tracing_pipeline` enable extension is not enabled
4455+ ┌─ wgsl:1:2
4456+ │
4457+ 1 │ @ray_generation
4458+ │ ^^^^^^^^^^^^^^ the `wgpu_ray_tracing_pipeline` \" Enable Extension\" is needed for this functionality, but it is not currently enabled.
4459+ │
4460+ = note: You can enable this extension by adding `enable wgpu_ray_tracing_pipeline;` at the top of the shader, before any other items.
4461+
4462+ " ,
4463+ Err ( naga:: valid:: ValidationError :: EntryPoint {
4464+ source: naga:: valid:: EntryPointError :: UnsupportedCapability ( naga:: valid:: Capabilities :: RAY_TRACING_PIPELINE ) ,
4465+ ..
4466+ } , )
4467+ ) ;
4468+ }
4469+
4470+ #[ test]
4471+ fn check_ray_tracing_pipeline_payload ( ) {
4472+ for space in [ "ray_payload" , "incoming_ray_payload" ] {
4473+ // ascii is a byte per char so length is fine
4474+ let space_arrows = "^" . to_string ( ) . repeat ( space. len ( ) ) ;
4475+ check_extension_validation ! (
4476+ Capabilities :: RAY_TRACING_PIPELINE ,
4477+ & format!( "var<{space}> payload: u32;" ) ,
4478+ & format!( "error: the `wgpu_ray_tracing_pipeline` enable extension is not enabled
4479+ ┌─ wgsl:1:5
4480+ │
4481+ 1 │ var<{space}> payload: u32;
4482+ │ {space_arrows} the `wgpu_ray_tracing_pipeline` \" Enable Extension\" is needed for this functionality, but it is not currently enabled.
4483+ │
4484+ = note: You can enable this extension by adding `enable wgpu_ray_tracing_pipeline;` at the top of the shader, before any other items.
4485+
4486+ " ) ,
4487+ Err ( naga:: valid:: ValidationError :: GlobalVariable {
4488+ source: naga:: valid:: GlobalVariableError :: UnsupportedCapability ( naga:: valid:: Capabilities :: RAY_TRACING_PIPELINE ) ,
4489+ ..
4490+ } , )
4491+ ) ;
4492+ }
4493+ }
4494+
4495+ #[ test]
4496+ fn check_ray_tracing_pipeline_incoming_payload_required ( ) {
4497+ for stage in [ "any_hit" , "closest_hit" , "miss" ] {
4498+ // ascii is a byte per char so length is fine
4499+ let stage_arrows = "^" . to_string ( ) . repeat ( stage. len ( ) ) ;
4500+ check (
4501+ & format ! ( "enable wgpu_ray_tracing_pipeline; @{stage} fn main() {{}}" ) ,
4502+ & format ! ( "error: incoming payload is missing on ray hit or miss shader entry point
4503+ ┌─ wgsl:1:36
4504+ │
4505+ 1 │ enable wgpu_ray_tracing_pipeline; @{stage} fn main() {{}}
4506+ │ {stage_arrows} must be paired with a `@incoming_payload` attribute
4507+
4508+ " ) ,
4509+ ) ;
4510+ }
4511+ }
4512+
4513+ #[ test]
4514+ fn check_ray_tracing_pipeline_payload_disallowed ( ) {
4515+ for ( stage, output, stmt) in [
4516+ (
4517+ "var<incoming_ray_payload> incoming: u32; @any_hit @incoming_payload(incoming)" ,
4518+ "" ,
4519+ "" ,
4520+ ) ,
4521+ ( "@compute @workgroup_size(1)" , "" , "" ) ,
4522+ (
4523+ "@vertex" ,
4524+ " -> @builtin(position) vec4<f32>" ,
4525+ "return vec4();" ,
4526+ ) ,
4527+ ( "@fragment" , "" , "" ) ,
4528+ ] {
4529+ check_one_validation ! (
4530+ & format!(
4531+ "enable wgpu_ray_tracing_pipeline;
4532+ @group(0) @binding(0) var acc_struct: acceleration_structure;
4533+ var<ray_payload> payload: u32;
4534+
4535+ {stage} fn main() {output} {{_ = payload; {stmt}}}"
4536+ ) ,
4537+ Err ( naga:: valid:: ValidationError :: EntryPoint {
4538+ source: naga:: valid:: EntryPointError :: RayPayloadInInvalidStage ,
4539+ ..
4540+ } , ) ,
4541+ Capabilities :: RAY_TRACING_PIPELINE
4542+ ) ;
4543+ }
4544+ }
0 commit comments