wgpu_core/indirect_validation/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use crate::{
    device::DeviceError,
    pipeline::{CreateComputePipelineError, CreateShaderModuleError},
};
use alloc::boxed::Box;
use thiserror::Error;

mod dispatch;
mod draw;
mod utils;

pub(crate) use dispatch::Dispatch;
pub(crate) use draw::{Draw, DrawBatcher, DrawResources};

#[derive(Clone, Debug, Error)]
#[non_exhaustive]
enum CreateIndirectValidationPipelineError {
    #[error(transparent)]
    DeviceError(#[from] DeviceError),
    #[error(transparent)]
    ShaderModule(#[from] CreateShaderModuleError),
    #[error(transparent)]
    ComputePipeline(#[from] CreateComputePipelineError),
}

pub(crate) struct IndirectValidation {
    pub(crate) dispatch: Dispatch,
    pub(crate) draw: Draw,
}

impl IndirectValidation {
    pub(crate) fn new(
        device: &dyn hal::DynDevice,
        required_limits: &wgt::Limits,
        required_features: &wgt::Features,
    ) -> Result<Self, DeviceError> {
        let dispatch = match Dispatch::new(device, required_limits) {
            Ok(dispatch) => dispatch,
            Err(e) => {
                log::error!("indirect-validation error: {e:?}");
                return Err(DeviceError::Lost);
            }
        };
        let draw = match Draw::new(device, required_features) {
            Ok(draw) => draw,
            Err(e) => {
                log::error!("indirect-draw-validation error: {e:?}");
                return Err(DeviceError::Lost);
            }
        };
        Ok(Self { dispatch, draw })
    }

    pub(crate) fn dispose(self, device: &dyn hal::DynDevice) {
        let Self { dispatch, draw } = self;

        dispatch.dispose(device);
        draw.dispose(device);
    }
}

#[derive(Debug)]
pub(crate) struct BindGroups {
    pub(crate) dispatch: Box<dyn hal::DynBindGroup>,
    draw: Box<dyn hal::DynBindGroup>,
}

impl BindGroups {
    /// `Ok(None)` will only be returned if `buffer_size` is `0`.
    pub(crate) fn new(
        indirect_validation: &IndirectValidation,
        device: &crate::device::Device,
        buffer_size: u64,
        buffer: &dyn hal::DynBuffer,
    ) -> Result<Option<Self>, DeviceError> {
        let dispatch = indirect_validation.dispatch.create_src_bind_group(
            device.raw(),
            &device.limits,
            buffer_size,
            buffer,
        )?;
        let draw = indirect_validation.draw.create_src_bind_group(
            device.raw(),
            &device.adapter.limits(),
            buffer_size,
            buffer,
        )?;

        match (dispatch, draw) {
            (None, None) => Ok(None),
            (None, Some(_)) => unreachable!(),
            (Some(_), None) => unreachable!(),
            (Some(dispatch), Some(draw)) => Ok(Some(Self { dispatch, draw })),
        }
    }

    pub(crate) fn dispose(self, device: &dyn hal::DynDevice) {
        let Self { dispatch, draw } = self;

        unsafe {
            device.destroy_bind_group(dispatch);
            device.destroy_bind_group(draw);
        }
    }
}