wgpu/backend/
custom.rs

1//! Provides wrappers custom backend implementations
2
3#![allow(ambiguous_wide_pointer_comparisons)]
4
5pub use crate::dispatch::*;
6
7use crate::cmp::AtomicU64;
8use alloc::boxed::Box;
9use alloc::sync::Arc;
10use core::sync::atomic::Ordering;
11
12macro_rules! dyn_type {
13    // cloning of arc forbidden
14    // but we still use it to provide Eq,Ord,Hash implementations
15    (pub mut struct $name:ident(dyn $interface:tt)) => {
16        #[derive(Debug)]
17        pub(crate) struct $name(Arc<dyn $interface>);
18        crate::cmp::impl_eq_ord_hash_arc_address!($name => .0);
19
20        impl $name {
21            pub(crate) fn new<T: $interface>(t: T) -> Self {
22                Self(Arc::new(t))
23            }
24
25            #[allow(clippy::allow_attributes, dead_code)]
26            pub(crate) fn downcast<T: $interface>(&self) -> Option<&T> {
27                self.0.as_ref().as_any().downcast_ref()
28            }
29        }
30
31        impl core::ops::Deref for $name {
32            type Target = dyn $interface;
33
34            #[inline]
35            fn deref(&self) -> &Self::Target {
36                self.0.as_ref()
37            }
38        }
39
40        impl core::ops::DerefMut for $name {
41            #[inline]
42            fn deref_mut(&mut self) -> &mut Self::Target {
43                Arc::get_mut(&mut self.0).expect("")
44            }
45        }
46    };
47    // cloning of arc is allowed
48    (pub ref struct $name:ident(dyn $interface:tt)) => {
49        #[derive(Debug, Clone)]
50        pub(crate) struct $name(Arc<dyn $interface>);
51        crate::cmp::impl_eq_ord_hash_arc_address!($name => .0);
52
53        impl $name {
54            pub(crate) fn new<T: $interface>(t: T) -> Self {
55                Self(Arc::new(t))
56            }
57
58            pub(crate) fn downcast<T: $interface>(&self) -> Option<&T> {
59                self.0.as_ref().as_any().downcast_ref()
60            }
61        }
62
63        impl core::ops::Deref for $name {
64            type Target = dyn $interface;
65
66            #[inline]
67            fn deref(&self) -> &Self::Target {
68                self.0.as_ref()
69            }
70        }
71    };
72}
73
74dyn_type!(pub ref struct DynContext(dyn InstanceInterface));
75dyn_type!(pub ref struct DynAdapter(dyn AdapterInterface));
76dyn_type!(pub ref struct DynDevice(dyn DeviceInterface));
77dyn_type!(pub ref struct DynQueue(dyn QueueInterface));
78dyn_type!(pub ref struct DynShaderModule(dyn ShaderModuleInterface));
79dyn_type!(pub ref struct DynBindGroupLayout(dyn BindGroupLayoutInterface));
80dyn_type!(pub ref struct DynBindGroup(dyn BindGroupInterface));
81dyn_type!(pub ref struct DynTextureView(dyn TextureViewInterface));
82dyn_type!(pub ref struct DynSampler(dyn SamplerInterface));
83dyn_type!(pub ref struct DynBuffer(dyn BufferInterface));
84dyn_type!(pub ref struct DynTexture(dyn TextureInterface));
85dyn_type!(pub ref struct DynExternalTexture(dyn ExternalTextureInterface));
86dyn_type!(pub ref struct DynBlas(dyn BlasInterface));
87dyn_type!(pub ref struct DynTlas(dyn TlasInterface));
88dyn_type!(pub ref struct DynQuerySet(dyn QuerySetInterface));
89dyn_type!(pub ref struct DynPipelineLayout(dyn PipelineLayoutInterface));
90dyn_type!(pub ref struct DynRenderPipeline(dyn RenderPipelineInterface));
91dyn_type!(pub ref struct DynComputePipeline(dyn ComputePipelineInterface));
92dyn_type!(pub ref struct DynPipelineCache(dyn PipelineCacheInterface));
93dyn_type!(pub mut struct DynCommandEncoder(dyn CommandEncoderInterface));
94dyn_type!(pub mut struct DynComputePass(dyn ComputePassInterface));
95dyn_type!(pub mut struct DynRenderPass(dyn RenderPassInterface));
96dyn_type!(pub mut struct DynCommandBuffer(dyn CommandBufferInterface));
97
98static NEXT_RENDER_BUNDLE_ENCODER_ID: AtomicU64 = AtomicU64::new(0);
99
100// DynRenderBundleEncoder uses Box instead of Arc so that finish_boxed(self: Box<Self>)
101// can be dispatched through the trait object (consuming the encoder).
102#[derive(Debug)]
103pub(crate) struct DynRenderBundleEncoder {
104    // Unique identity for Eq/Ord/Hash. The data pointer of the boxed trait object is
105    // not safe to use for identity because ZST impls share the same dangling address.
106    id: u64,
107    inner: Box<dyn RenderBundleEncoderInterface>,
108}
109
110impl DynRenderBundleEncoder {
111    pub(crate) fn new<T: RenderBundleEncoderInterface>(t: T) -> Self {
112        Self {
113            id: NEXT_RENDER_BUNDLE_ENCODER_ID.fetch_add(1, Ordering::Relaxed),
114            inner: Box::new(t),
115        }
116    }
117
118    pub(crate) fn downcast<T: RenderBundleEncoderInterface>(&self) -> Option<&T> {
119        self.inner.as_ref().as_any().downcast_ref()
120    }
121
122    pub(crate) fn finish_boxed(
123        self,
124        desc: &crate::RenderBundleDescriptor<'_>,
125    ) -> crate::dispatch::DispatchRenderBundle {
126        self.inner.finish_boxed(desc)
127    }
128}
129
130impl core::ops::Deref for DynRenderBundleEncoder {
131    type Target = dyn RenderBundleEncoderInterface;
132    #[inline]
133    fn deref(&self) -> &Self::Target {
134        self.inner.as_ref()
135    }
136}
137
138impl core::ops::DerefMut for DynRenderBundleEncoder {
139    #[inline]
140    fn deref_mut(&mut self) -> &mut Self::Target {
141        self.inner.as_mut()
142    }
143}
144
145// Eq/Ord/Hash for DynRenderBundleEncoder are based on a unique id assigned at construction.
146//
147// These impls are not semantically meaningful (we never sort or deduplicate encoders by
148// "value") but are required to satisfy bounds imposed by the dispatch enum machinery.
149impl PartialEq for DynRenderBundleEncoder {
150    fn eq(&self, other: &Self) -> bool {
151        self.id == other.id
152    }
153}
154impl Eq for DynRenderBundleEncoder {}
155
156impl PartialOrd for DynRenderBundleEncoder {
157    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
158        Some(self.cmp(other))
159    }
160}
161impl Ord for DynRenderBundleEncoder {
162    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
163        self.id.cmp(&other.id)
164    }
165}
166
167impl core::hash::Hash for DynRenderBundleEncoder {
168    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
169        self.id.hash(state);
170    }
171}
172
173dyn_type!(pub ref struct DynRenderBundle(dyn RenderBundleInterface));
174dyn_type!(pub ref struct DynSurface(dyn SurfaceInterface));
175dyn_type!(pub ref struct DynSurfaceOutputDetail(dyn SurfaceOutputDetailInterface));
176dyn_type!(pub mut struct DynQueueWriteBuffer(dyn QueueWriteBufferInterface));
177dyn_type!(pub mut struct DynBufferMappedRange(dyn BufferMappedRangeInterface));