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(
89 indirect_validation: &IndirectValidation,
90 device: &crate::device::Device,
91 buffer_size: u64,
92 buffer: &dyn hal::DynBuffer,
93 ) -> Result<Option<Self>, DeviceError> {
94 let dispatch = indirect_validation.dispatch.create_src_bind_group(
95 device.raw(),
96 &device.limits,
97 buffer_size,
98 buffer,
99 device.instance_flags,
100 )?;
101 let draw = indirect_validation.draw.create_src_bind_group(
102 device.raw(),
103 &device.adapter.limits(),
104 buffer_size,
105 buffer,
106 device.instance_flags,
107 )?;
108
109 match (dispatch, draw) {
110 (None, None) => Ok(None),
111 (None, Some(_)) => unreachable!(),
112 (Some(_), None) => unreachable!(),
113 (Some(dispatch), Some(draw)) => Ok(Some(Self { dispatch, draw })),
114 }
115 }
116
117 pub(crate) fn dispose(self, device: &dyn hal::DynDevice) {
118 let Self { dispatch, draw } = self;
119
120 unsafe {
121 device.destroy_bind_group(dispatch);
122 device.destroy_bind_group(draw);
123 }
124 }
125}