@@ -69,17 +69,24 @@ impl fmt::Debug for RayTracingPass {
6969
7070impl RayTracingPass {
7171 /// If the parent command encoder is invalid, the returned pass will be invalid.
72- fn new ( parent : Arc < CommandEncoder > , desc : RayTracingPassDescriptor ) -> Self {
72+ fn new (
73+ parent : Arc < CommandEncoder > ,
74+ desc : RayTracingPassDescriptor ,
75+ ) -> Result < Self , MissingFeatures > {
76+ parent
77+ . device
78+ . require_features ( wgt:: Features :: EXPERIMENTAL_RAY_TRACING_PIPELINES ) ?;
79+
7380 let RayTracingPassDescriptor { label } = desc;
7481
75- Self {
82+ Ok ( Self {
7683 base : BasePass :: new ( & label) ,
7784 device : parent. device . clone ( ) ,
7885 parent : Some ( parent) ,
7986
8087 current_bind_groups : BindGroupStateChange :: new ( ) ,
8188 current_pipeline : StateChange :: new ( ) ,
82- }
89+ } )
8390 }
8491
8592 fn new_invalid ( parent : Arc < CommandEncoder > , label : & Label , err : RayTracingPassError ) -> Self {
@@ -193,6 +200,10 @@ pub enum TraceRayError {
193200 TooManyTotal { current : u32 , limit : u32 } ,
194201 #[ error( transparent) ]
195202 BindingSizeTooSmall ( #[ from] LateMinBufferBindingSizeMismatch ) ,
203+ #[ error( "Not all immediate data required by the pipeline has been set via set_immediates (missing byte ranges: {missing})" ) ]
204+ MissingImmediateData {
205+ missing : naga:: valid:: ImmediateSlots ,
206+ } ,
196207}
197208
198209impl WebGpuError for TraceRayError {
@@ -328,6 +339,18 @@ impl<'scope, 'snatch_guard, 'cmd_enc> State<'scope, 'snatch_guard, 'cmd_enc> {
328339 if let Some ( pipeline) = self . pipeline . as_ref ( ) {
329340 self . pass . binder . check_compatibility ( pipeline. as_ref ( ) ) ?;
330341 self . pass . binder . check_late_buffer_bindings ( ) ?;
342+ if !self
343+ . pass
344+ . immediate_state
345+ . immediate_slots_set
346+ . contains ( pipeline. immediate_slots_required )
347+ {
348+ return Err ( TraceRayError :: MissingImmediateData {
349+ missing : pipeline
350+ . immediate_slots_required
351+ . difference ( self . pass . immediate_state . immediate_slots_set ) ,
352+ } ) ;
353+ }
331354 Ok ( ( ) )
332355 } else {
333356 Err ( TraceRayError :: MissingPipeline ( pass:: MissingPipeline ) )
@@ -558,6 +581,7 @@ impl CommandEncoder {
558581 let label = desc. label . as_deref ( ) . map ( Cow :: Borrowed ) ;
559582
560583 let scope = PassErrorScope :: Pass ;
584+
561585 let mut cmd_buf_data = self . data . lock ( ) ;
562586
563587 match cmd_buf_data. lock_encoder ( ) {
@@ -570,10 +594,26 @@ impl CommandEncoder {
570594 ) ;
571595 }
572596
573- (
574- RayTracingPass :: new ( self . clone ( ) , RayTracingPassDescriptor { label } ) ,
575- None ,
576- )
597+ let pass = match RayTracingPass :: new (
598+ self . clone ( ) ,
599+ RayTracingPassDescriptor {
600+ label : label. clone ( ) ,
601+ } ,
602+ ) {
603+ Ok ( pass) => pass,
604+ Err ( err) => {
605+ return (
606+ RayTracingPass :: new_invalid (
607+ self . clone ( ) ,
608+ & label,
609+ err. map_pass_err ( scope) ,
610+ ) ,
611+ None ,
612+ ) ;
613+ }
614+ } ;
615+
616+ ( pass, None )
577617 }
578618 Err ( err @ SErr :: Locked ) => {
579619 // Attempting to open a new pass while the encoder is locked
@@ -818,9 +858,15 @@ fn trace_rays(
818858 // `saturating_mul` is fine here as it is the limit, so a lower limit if it would overflow is just a
819859 // slightly greater restriction.
820860 let dim_size_limit = [
821- limits. max_compute_workgroup_size_x . saturating_mul ( limits. max_compute_workgroups_per_dimension ) ,
822- limits. max_compute_workgroup_size_y . saturating_mul ( limits. max_compute_workgroups_per_dimension ) ,
823- limits. max_compute_workgroup_size_z . saturating_mul ( limits. max_compute_workgroups_per_dimension ) ,
861+ limits
862+ . max_compute_workgroup_size_x
863+ . saturating_mul ( limits. max_compute_workgroups_per_dimension ) ,
864+ limits
865+ . max_compute_workgroup_size_y
866+ . saturating_mul ( limits. max_compute_workgroups_per_dimension ) ,
867+ limits
868+ . max_compute_workgroup_size_z
869+ . saturating_mul ( limits. max_compute_workgroups_per_dimension ) ,
824870 ] ;
825871
826872 if dims[ 0 ] > dim_size_limit[ 0 ] {
@@ -850,7 +896,9 @@ fn trace_rays(
850896 ) ) ;
851897 }
852898
853- let tot_rays = dims[ 0 ] . checked_mul ( dims[ 1 ] ) . and_then ( |tmp| tmp. checked_mul ( dims[ 2 ] ) ) ;
899+ let tot_rays = dims[ 0 ]
900+ . checked_mul ( dims[ 1 ] )
901+ . and_then ( |tmp| tmp. checked_mul ( dims[ 2 ] ) ) ;
854902
855903 if tot_rays. is_none_or ( |tot_rays| tot_rays > limits. max_ray_dispatch_count ) {
856904 return Err ( RayTracingPassErrorInner :: TraceRay (
0 commit comments