Skip to main content

dawn_wgpu/
types.rs

1use dawn_rs::*;
2use std::fmt;
3use std::ops::Deref;
4use std::sync::Arc;
5
6type InstanceJob = Box<dyn FnOnce(&mut DawnInstanceState) + Send + 'static>;
7
8#[derive(Debug)]
9pub(crate) struct DawnInstanceWorker {
10    sender: std::sync::mpsc::Sender<InstanceJob>,
11}
12
13#[derive(Debug)]
14pub(crate) struct DawnInstanceState {
15    pub(crate) instance: Instance,
16}
17
18impl DawnInstanceState {
19    fn new(instance: Instance) -> Self {
20        Self { instance }
21    }
22}
23
24pub struct DawnInstance {
25    pub(crate) inner: Arc<DawnInstanceWorker>,
26    #[cfg(feature = "wire")]
27    pub(crate) wire_handle: Option<Arc<crate::wire_backend::WireBackendHandle>>,
28}
29
30impl DawnInstance {
31    pub(crate) fn from_factory(
32        factory: impl FnOnce() -> Instance + Send + 'static,
33        #[cfg(feature = "wire")] wire_handle: Option<Arc<crate::wire_backend::WireBackendHandle>>,
34    ) -> Self {
35        let (sender, receiver) = std::sync::mpsc::channel::<InstanceJob>();
36        std::thread::spawn(move || {
37            let mut state = DawnInstanceState::new(factory());
38            while let Ok(job) = receiver.recv() {
39                job(&mut state);
40            }
41        });
42        Self {
43            inner: Arc::new(DawnInstanceWorker { sender }),
44            #[cfg(feature = "wire")]
45            wire_handle,
46        }
47    }
48
49    pub(crate) fn with_instance<R: Send + 'static>(
50        &self,
51        f: impl FnOnce(&mut DawnInstanceState) -> R + Send + 'static,
52    ) -> R {
53        let (sender, receiver) = std::sync::mpsc::channel::<R>();
54        self.inner
55            .sender
56            .send(Box::new(move |state| {
57                let result = f(state);
58                let _ = sender.send(result);
59            }))
60            .expect("wgpu-compat: failed to send instance task to worker");
61        receiver
62            .recv()
63            .expect("wgpu-compat: failed to receive instance task result")
64    }
65}
66
67unsafe impl Send for DawnAdapterShared {}
68unsafe impl Sync for DawnAdapterShared {}
69
70impl Clone for DawnInstance {
71    fn clone(&self) -> Self {
72        Self {
73            inner: Arc::clone(&self.inner),
74            #[cfg(feature = "wire")]
75            wire_handle: self.wire_handle.clone(),
76        }
77    }
78}
79
80impl fmt::Debug for DawnInstance {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        let mut dbg = f.debug_struct("DawnInstance");
83        dbg.field("inner", &"worker-thread");
84        #[cfg(feature = "wire")]
85        dbg.field("wire_handle", &self.wire_handle.is_some());
86        dbg.finish()
87    }
88}
89
90#[derive(Clone)]
91pub struct DawnAdapter {
92    pub(crate) shared: Arc<DawnAdapterShared>,
93}
94
95impl DawnAdapter {
96    pub(crate) fn from_adapter(worker: Arc<DawnInstanceWorker>, adapter: Adapter) -> Self {
97        let raw = Box::into_raw(Box::new(adapter));
98        Self {
99            shared: Arc::new(DawnAdapterShared {
100                worker,
101                raw,
102            }),
103        }
104    }
105
106    pub(crate) fn with_adapter<R: Send + 'static>(
107        &self,
108        f: impl FnOnce(&Adapter) -> R + Send + 'static,
109    ) -> R {
110        let raw = self.shared.raw as usize;
111        let (sender, receiver) = std::sync::mpsc::channel::<R>();
112        self.shared
113            .worker
114            .sender
115            .send(Box::new(move |_state| {
116                // SAFETY: raw points to a valid boxed Adapter for the lifetime of shared.
117                let adapter = unsafe { &*(raw as *mut Adapter) };
118                let result = f(adapter);
119                let _ = sender.send(result);
120            }))
121            .expect("wgpu-compat: failed to send adapter task to worker");
122        receiver
123            .recv()
124            .expect("wgpu-compat: failed to receive adapter task result")
125    }
126}
127
128#[derive(Debug)]
129pub(crate) struct DawnAdapterShared {
130    worker: Arc<DawnInstanceWorker>,
131    raw: *mut Adapter,
132}
133
134impl Drop for DawnAdapterShared {
135    fn drop(&mut self) {
136        let raw = self.raw as usize;
137        let _ = self.worker.sender.send(Box::new(move |_state| {
138            // SAFETY: raw originated from Box::into_raw and is dropped exactly once here.
139            unsafe { drop(Box::from_raw(raw as *mut Adapter)) };
140        }));
141    }
142}
143
144impl fmt::Debug for DawnAdapter {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        f.debug_struct("DawnAdapter")
147            .field("raw", &self.shared.raw)
148            .finish()
149    }
150}
151
152#[derive(Clone)]
153pub struct DawnDevice {
154    pub(crate) inner: Device,
155    pub(crate) device_lost_callback:
156        Arc<std::sync::Mutex<Option<wgpu::custom::BoxDeviceLostCallback>>>,
157    pub(crate) uncaptured_error_handler:
158        Arc<std::sync::Mutex<Option<Arc<dyn wgpu::UncapturedErrorHandler>>>>,
159}
160
161impl DawnDevice {
162    pub(crate) fn new(device: Device) -> Self {
163        Self {
164            inner: device,
165            device_lost_callback: Arc::new(std::sync::Mutex::new(None)),
166            uncaptured_error_handler: Arc::new(std::sync::Mutex::new(None)),
167        }
168    }
169
170    pub(crate) fn with_callback_state(
171        device: Device,
172        device_lost_callback: Arc<std::sync::Mutex<Option<wgpu::custom::BoxDeviceLostCallback>>>,
173        uncaptured_error_handler: Arc<std::sync::Mutex<Option<Arc<dyn wgpu::UncapturedErrorHandler>>>>,
174    ) -> Self {
175        Self {
176            inner: device,
177            device_lost_callback,
178            uncaptured_error_handler,
179        }
180    }
181}
182
183impl fmt::Debug for DawnDevice {
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        f.debug_struct("DawnDevice")
186            .field("inner", &self.inner)
187            .finish()
188    }
189}
190
191#[derive(Debug, Clone)]
192pub struct DawnQueue {
193    pub(crate) inner: Queue,
194}
195
196#[derive(Debug, Clone)]
197pub struct DawnShaderModule {
198    pub(crate) inner: ShaderModule,
199}
200
201#[derive(Debug, Clone)]
202pub struct DawnBindGroupLayout {
203    pub(crate) inner: BindGroupLayout,
204}
205
206#[derive(Debug, Clone)]
207pub struct DawnBindGroup {
208    pub(crate) inner: BindGroup,
209}
210
211#[derive(Debug, Clone)]
212pub struct DawnTextureView {
213    pub(crate) inner: TextureView,
214}
215
216#[derive(Debug, Clone)]
217pub struct DawnSampler {
218    pub(crate) inner: Sampler,
219}
220
221#[derive(Debug, Clone)]
222pub struct DawnBuffer {
223    pub(crate) inner: Buffer,
224}
225
226#[derive(Debug, Clone)]
227pub struct DawnTexture {
228    pub(crate) inner: Texture,
229}
230
231#[derive(Debug, Clone)]
232pub struct DawnExternalTexture {
233    pub(crate) inner: ExternalTexture,
234}
235
236#[derive(Debug, Clone)]
237pub struct DawnQuerySet {
238    pub(crate) inner: QuerySet,
239}
240
241#[derive(Debug, Clone)]
242pub struct DawnPipelineLayout {
243    pub(crate) inner: PipelineLayout,
244}
245
246#[derive(Debug, Clone)]
247pub struct DawnRenderPipeline {
248    pub(crate) inner: RenderPipeline,
249}
250
251#[derive(Debug, Clone)]
252pub struct DawnComputePipeline {
253    pub(crate) inner: ComputePipeline,
254}
255
256#[derive(Debug)]
257pub struct DawnCommandEncoder {
258    pub(crate) inner: CommandEncoder,
259}
260
261#[derive(Debug)]
262pub struct DawnComputePass {
263    pub(crate) inner: ComputePassEncoder,
264    pub(crate) ended: bool,
265}
266
267#[derive(Debug)]
268pub struct DawnRenderPass {
269    pub(crate) inner: RenderPassEncoder,
270    pub(crate) ended: bool,
271}
272
273#[derive(Debug)]
274pub struct DawnCommandBuffer {
275    pub(crate) inner: CommandBuffer,
276}
277
278#[derive(Debug)]
279pub struct DawnRenderBundleEncoder {
280    pub(crate) inner: RenderBundleEncoder,
281}
282
283#[derive(Debug, Clone)]
284pub struct DawnRenderBundle {
285    pub(crate) inner: RenderBundle,
286}
287
288#[cfg(target_os = "macos")]
289#[derive(Debug)]
290pub struct MetalLayerHandle {
291    pub(crate) ptr: *mut std::ffi::c_void,
292}
293
294#[cfg(target_os = "macos")]
295unsafe impl Send for MetalLayerHandle {}
296#[cfg(target_os = "macos")]
297unsafe impl Sync for MetalLayerHandle {}
298
299#[cfg(target_os = "macos")]
300impl Drop for MetalLayerHandle {
301    fn drop(&mut self) {
302        if self.ptr.is_null() {
303            return;
304        }
305        unsafe {
306            let ptr = self.ptr.cast::<objc2_quartz_core::CAMetalLayer>();
307            let _ = objc2::rc::Retained::from_raw(ptr);
308        }
309    }
310}
311
312#[derive(Debug, Clone)]
313pub struct DawnSurface {
314    pub(crate) inner: Surface,
315    #[cfg(target_os = "macos")]
316    pub(crate) metal_layer: Option<Arc<MetalLayerHandle>>,
317}
318
319#[derive(Debug, Clone)]
320pub struct DawnSurfaceOutputDetail {
321    pub(crate) surface: Surface,
322}
323
324#[derive(Debug)]
325pub struct DawnQueueWriteBuffer {
326    pub(crate) inner: Vec<u8>,
327}
328
329#[derive(Debug)]
330pub struct DawnBufferMappedRange {
331    pub(crate) data: *mut u8,
332    pub(crate) size: usize,
333}
334
335unsafe impl Send for DawnBufferMappedRange {}
336unsafe impl Sync for DawnBufferMappedRange {}
337
338#[derive(Debug)]
339pub struct DawnPipelineCache;
340
341#[derive(Debug)]
342pub struct DawnBlas;
343
344#[derive(Debug)]
345pub struct DawnTlas;
346
347macro_rules! impl_deref_to_inner {
348    ($name:ident, $target:ty) => {
349        impl Deref for $name {
350            type Target = $target;
351
352            fn deref(&self) -> &Self::Target {
353                &self.inner
354            }
355        }
356    };
357}
358
359impl_deref_to_inner!(DawnDevice, Device);
360impl_deref_to_inner!(DawnQueue, Queue);
361impl_deref_to_inner!(DawnShaderModule, ShaderModule);
362impl_deref_to_inner!(DawnBindGroupLayout, BindGroupLayout);
363impl_deref_to_inner!(DawnBindGroup, BindGroup);
364impl_deref_to_inner!(DawnTextureView, TextureView);
365impl_deref_to_inner!(DawnSampler, Sampler);
366impl_deref_to_inner!(DawnBuffer, Buffer);
367impl_deref_to_inner!(DawnTexture, Texture);
368impl_deref_to_inner!(DawnExternalTexture, ExternalTexture);
369impl_deref_to_inner!(DawnQuerySet, QuerySet);
370impl_deref_to_inner!(DawnPipelineLayout, PipelineLayout);
371impl_deref_to_inner!(DawnRenderPipeline, RenderPipeline);
372impl_deref_to_inner!(DawnComputePipeline, ComputePipeline);
373impl_deref_to_inner!(DawnCommandEncoder, CommandEncoder);
374impl_deref_to_inner!(DawnComputePass, ComputePassEncoder);
375impl_deref_to_inner!(DawnRenderPass, RenderPassEncoder);
376impl_deref_to_inner!(DawnCommandBuffer, CommandBuffer);
377impl_deref_to_inner!(DawnRenderBundleEncoder, RenderBundleEncoder);
378impl_deref_to_inner!(DawnRenderBundle, RenderBundle);
379impl_deref_to_inner!(DawnSurface, Surface);