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 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 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);