wgpu_core/indirect_validation/
mod.rs1use crate::{
2 device::DeviceError,
3 pipeline::{CreateComputePipelineError, CreateShaderModuleError},
4};
5use alloc::boxed::Box;
6use scopeguard::{guard, ScopeGuard};
7use thiserror::Error;
8
9mod dispatch;
10mod draw;
11mod utils;
12
13pub(crate) use dispatch::Dispatch;
14pub(crate) use draw::{Draw, DrawBatcher, DrawResources};
15
16#[derive(Clone, Debug, Error)]
17#[non_exhaustive]
18enum CreateIndirectValidationPipelineError {
19 #[error(transparent)]
20 DeviceError(#[from] DeviceError),
21 #[error(transparent)]
22 ShaderModule(#[from] CreateShaderModuleError),
23 #[error(transparent)]
24 ComputePipeline(#[from] CreateComputePipelineError),
25}
26
27pub(crate) struct IndirectValidation {
28 pub(crate) dispatch: Dispatch,
29 pub(crate) draw: Draw,
30}
31
32impl IndirectValidation {
33 pub(crate) fn new(
34 device: &dyn hal::DynDevice,
35 required_limits: &wgt::Limits,
36 required_features: &wgt::Features,
37 instance_flags: wgt::InstanceFlags,
38 backend: wgt::Backend,
39 ) -> Result<Self, DeviceError> {
40 let dispatch = match Dispatch::new(device, instance_flags, required_limits) {
41 Ok(dispatch) => dispatch,
42 Err(e) => {
43 log::error!("indirect-validation error: {e:?}");
44 return Err(DeviceError::Lost);
45 }
46 };
47 let dispatch = guard(dispatch, |dispatch| dispatch.dispose(device));
48
49 let draw = match Draw::new(
50 device,
51 required_features,
52 instance_flags,
53 backend,
54 required_limits,
55 ) {
56 Ok(draw) => draw,
57 Err(e) => {
58 log::error!("indirect-draw-validation error: {e:?}");
59 return Err(DeviceError::Lost);
60 }
61 };
62 Ok(Self {
63 dispatch: ScopeGuard::into_inner(dispatch),
64 draw,
65 })
66 }
67
68 pub(crate) fn dispose(self, device: &dyn hal::DynDevice) {
69 let Self { dispatch, draw } = self;
70
71 dispatch.dispose(device);
72 draw.dispose(device);
73 }
74}
75
76#[derive(Debug)]
77pub(crate) struct BindGroups {
78 pub(crate) dispatch: Box<dyn hal::DynBindGroup>,
79 draw: Box<dyn hal::DynBindGroup>,
80}
81
82impl BindGroups {
83 pub(crate) fn new(
85 indirect_validation: &IndirectValidation,
86 device: &crate::device::Device,
87 buffer_size: u64,
88 buffer: &dyn hal::DynBuffer,
89 ) -> Result<Option<Self>, DeviceError> {
90 let dispatch = indirect_validation.dispatch.create_src_bind_group(
91 device.raw(),
92 &device.limits,
93 buffer_size,
94 buffer,
95 device.instance_flags,
96 )?;
97 let draw = indirect_validation.draw.create_src_bind_group(
98 device.raw(),
99 &device.adapter.limits(),
100 buffer_size,
101 buffer,
102 device.instance_flags,
103 )?;
104
105 match (dispatch, draw) {
106 (None, None) => Ok(None),
107 (None, Some(_)) => unreachable!(),
108 (Some(_), None) => unreachable!(),
109 (Some(dispatch), Some(draw)) => Ok(Some(Self { dispatch, draw })),
110 }
111 }
112
113 pub(crate) fn dispose(self, device: &dyn hal::DynDevice) {
114 let Self { dispatch, draw } = self;
115
116 unsafe {
117 device.destroy_bind_group(dispatch);
118 device.destroy_bind_group(draw);
119 }
120 }
121}