Skip to content

Commit 87d2982

Browse files
committed
More pass validation
1 parent 8ef8b5e commit 87d2982

4 files changed

Lines changed: 87 additions & 11 deletions

File tree

tests/tests/wgpu-gpu/ray_tracing/pipelines.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use wgpu_types::AccelerationStructureFlags;
1010

1111
pub fn all_tests(tests: &mut Vec<GpuTestInitializer>) {
1212
tests.push(PIPELINE_CREATE_USE);
13+
tests.push(RAY_TRACING_PASS_NO_FEATURE);
1314
}
1415

1516
#[apply(gpu_test!)]
@@ -199,3 +200,19 @@ fn pipeline_create_use(ctx: TestingContext) {
199200
None,
200201
);
201202
}
203+
204+
#[apply(gpu_test!)]
205+
static RAY_TRACING_PASS_NO_FEATURE: GpuTestConfiguration = GpuTestConfiguration::new()
206+
.parameters(TestParameters::default())
207+
.run_sync(ray_tracing_pass_no_feature);
208+
209+
fn ray_tracing_pass_no_feature(ctx: TestingContext) {
210+
let mut encoder = ctx
211+
.device
212+
.create_command_encoder(&CommandEncoderDescriptor::default());
213+
214+
let pass = encoder.begin_ray_tracing_pass(&RayTracingPassDescriptor::default());
215+
drop(pass);
216+
217+
fail(&ctx.device, || encoder.finish(), None);
218+
}

wgpu-core/src/command/ray_tracing_pass.rs

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,24 @@ impl fmt::Debug for RayTracingPass {
6969

7070
impl 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

198209
impl 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(

wgpu-core/src/device/ray_tracing.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,14 @@ impl Device {
750750
desc.intersections.len(),
751751
)?;
752752

753+
let naga::valid::ImmediateUsage::Valid {
754+
slots: immediate_slots_required,
755+
size: _,
756+
} = io.immediates
757+
else {
758+
unreachable!("Immediates exceeding maxImmediateSize should have been rejected");
759+
};
760+
753761
let pipeline = pipeline::RayTracingPipeline {
754762
state: ResourceState::Valid(pipeline::RayTracingPipelineState {
755763
raw: ManuallyDrop::new(raw),
@@ -759,6 +767,7 @@ impl Device {
759767
}),
760768
device: self.clone(),
761769
late_sized_buffer_groups,
770+
immediate_slots_required,
762771
label: desc.label.to_string(),
763772
tracking_data: TrackingData::new(self.tracker_indices.ray_tracing_pipelines.clone()),
764773
};

wgpu-core/src/pipeline.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,7 @@ pub struct RayTracingPipeline {
14361436
pub(crate) state: ResourceState<RayTracingPipelineState>,
14371437
pub(crate) device: Arc<Device>,
14381438
pub(crate) late_sized_buffer_groups: ArrayVec<LateSizedBufferGroup, { hal::MAX_BIND_GROUPS }>,
1439+
pub(crate) immediate_slots_required: naga::valid::ImmediateSlots,
14391440
/// The `label` from the descriptor used to create the resource.
14401441
pub(crate) label: String,
14411442
pub(crate) tracking_data: TrackingData,
@@ -1486,6 +1487,7 @@ impl RayTracingPipeline {
14861487
tracking_data: TrackingData::new(device.tracker_indices.compute_pipelines.clone()),
14871488
state: ResourceState::Invalid,
14881489
device,
1490+
immediate_slots_required: naga::valid::ImmediateSlots::default(),
14891491
late_sized_buffer_groups: ArrayVec::new(),
14901492
label,
14911493
})

0 commit comments

Comments
 (0)