wgpu_core/indirect_validation/
mod.rs

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