1use core::{mem::ManuallyDrop, ops::Deref};
2
3use alloc::sync::Arc;
4use hal::DynResource;
5
6use crate::{
7 global::Global,
8 id::{
9 AdapterId, BlasId, BufferId, CommandEncoderId, DeviceId, QueueId, SurfaceId, TextureId,
10 TextureViewId, TlasId,
11 },
12 lock::RankData,
13 resource::RawResourceAccess,
14 snatch::SnatchGuard,
15};
16
17struct SimpleResourceGuard<Resource, HalType> {
19 _guard: Resource,
20 ptr: *const HalType,
21}
22
23impl<Resource, HalType> SimpleResourceGuard<Resource, HalType> {
24 pub fn new<C>(guard: Resource, callback: C) -> Option<Self>
26 where
27 C: Fn(&Resource) -> Option<&HalType>,
28 {
29 let ptr: *const HalType = callback(&guard)?;
31
32 Some(Self { _guard: guard, ptr })
33 }
34}
35
36impl<Resource, HalType> Deref for SimpleResourceGuard<Resource, HalType> {
37 type Target = HalType;
38
39 fn deref(&self) -> &Self::Target {
40 unsafe { &*self.ptr }
43 }
44}
45
46unsafe impl<Resource, HalType> Send for SimpleResourceGuard<Resource, HalType>
47where
48 Resource: Send,
49 HalType: Send,
50{
51}
52unsafe impl<Resource, HalType> Sync for SimpleResourceGuard<Resource, HalType>
53where
54 Resource: Sync,
55 HalType: Sync,
56{
57}
58
59struct SnatchableResourceGuard<Resource, HalType>
61where
62 Resource: RawResourceAccess,
63{
64 resource: Arc<Resource>,
65 snatch_lock_rank_data: ManuallyDrop<RankData>,
66 ptr: *const HalType,
67}
68
69impl<Resource, HalType> SnatchableResourceGuard<Resource, HalType>
70where
71 Resource: RawResourceAccess,
72 HalType: 'static,
73{
74 pub fn new(resource: Arc<Resource>) -> Option<Self> {
80 let snatch_guard = resource.device().snatchable_lock.read();
82
83 let underlying = resource
85 .raw(&snatch_guard)?
86 .as_any()
87 .downcast_ref::<HalType>()?;
88
89 let ptr: *const HalType = underlying;
92
93 let snatch_lock_rank_data = SnatchGuard::forget(snatch_guard);
96
97 Some(Self {
100 resource,
101 snatch_lock_rank_data: ManuallyDrop::new(snatch_lock_rank_data),
102 ptr,
103 })
104 }
105}
106
107impl<Resource, HalType> Deref for SnatchableResourceGuard<Resource, HalType>
108where
109 Resource: RawResourceAccess,
110{
111 type Target = HalType;
112
113 fn deref(&self) -> &Self::Target {
114 unsafe { &*self.ptr }
118 }
119}
120
121impl<Resource, HalType> Drop for SnatchableResourceGuard<Resource, HalType>
122where
123 Resource: RawResourceAccess,
124{
125 fn drop(&mut self) {
126 let data = unsafe { ManuallyDrop::take(&mut self.snatch_lock_rank_data) };
129
130 unsafe {
135 self.resource
136 .device()
137 .snatchable_lock
138 .force_unlock_read(data)
139 };
140 }
141}
142
143unsafe impl<Resource, HalType> Send for SnatchableResourceGuard<Resource, HalType>
144where
145 Resource: RawResourceAccess + Send,
146 HalType: Send,
147{
148}
149unsafe impl<Resource, HalType> Sync for SnatchableResourceGuard<Resource, HalType>
150where
151 Resource: RawResourceAccess + Sync,
152 HalType: Sync,
153{
154}
155
156impl crate::resource::Buffer {
157 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Buffer>> {
161 profiling::scope!("Buffer::as_hal");
162
163 SnatchableResourceGuard::new(self)
164 }
165}
166
167impl crate::resource::Texture {
168 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Texture>> {
172 profiling::scope!("Texture::as_hal");
173
174 SnatchableResourceGuard::new(self)
175 }
176}
177
178impl crate::resource::TextureView {
179 pub unsafe fn as_hal<A: hal::Api>(
183 self: Arc<Self>,
184 ) -> Option<impl Deref<Target = A::TextureView>> {
185 profiling::scope!("TextureView::as_hal");
186
187 SnatchableResourceGuard::new(self)
188 }
189}
190
191impl crate::instance::Adapter {
192 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Adapter>> {
196 profiling::scope!("Adapter::as_hal");
197
198 SimpleResourceGuard::new(self, move |adapter| {
199 adapter.raw.adapter.as_any().downcast_ref()
200 })
201 }
202}
203
204impl crate::device::Device {
205 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Device>> {
209 profiling::scope!("Device::as_hal");
210
211 SimpleResourceGuard::new(self, move |device| device.raw().as_any().downcast_ref())
212 }
213
214 pub unsafe fn fence_as_hal<A: hal::Api>(
218 self: Arc<Self>,
219 ) -> Option<impl Deref<Target = A::Fence>> {
220 profiling::scope!("Device::fence_as_hal");
221
222 SimpleResourceGuard::new(self, move |device| device.fence.as_any().downcast_ref())
223 }
224}
225
226impl crate::instance::Surface {
227 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Surface>> {
231 profiling::scope!("Surface::as_hal");
232
233 SimpleResourceGuard::new(self, move |surface| {
234 surface.raw(A::VARIANT)?.as_any().downcast_ref()
235 })
236 }
237}
238
239impl crate::command::CommandEncoder {
240 pub unsafe fn as_hal_mut<A: hal::Api, F: FnOnce(Option<&mut A::CommandEncoder>) -> R, R>(
250 self: &Arc<Self>,
251 hal_command_encoder_callback: F,
252 ) -> R {
253 profiling::scope!("CommandEncoder::as_hal");
254
255 let mut cmd_buf_data = self.data.lock();
256 cmd_buf_data.record_as_hal_mut(|opt_cmd_buf| -> R {
257 hal_command_encoder_callback(opt_cmd_buf.and_then(|cmd_buf| {
258 cmd_buf
259 .encoder
260 .open()
261 .ok()
262 .and_then(|encoder| encoder.as_any_mut().downcast_mut())
263 }))
264 })
265 }
266}
267
268impl crate::device::queue::Queue {
269 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Queue>> {
273 profiling::scope!("Queue::as_hal");
274
275 SimpleResourceGuard::new(self, move |queue| queue.raw().as_any().downcast_ref())
276 }
277}
278
279impl crate::resource::Blas {
280 pub unsafe fn as_hal<A: hal::Api>(
284 self: Arc<Self>,
285 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
286 profiling::scope!("Blas::as_hal");
287
288 SnatchableResourceGuard::new(self)
289 }
290}
291
292impl crate::resource::Tlas {
293 pub unsafe fn as_hal<A: hal::Api>(
297 self: Arc<Self>,
298 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
299 profiling::scope!("Tlas::as_hal");
300
301 SnatchableResourceGuard::new(self)
302 }
303}
304
305impl Global {
306 pub unsafe fn buffer_as_hal<A: hal::Api>(
310 &self,
311 id: BufferId,
312 ) -> Option<impl Deref<Target = A::Buffer>> {
313 let hub = &self.hub;
314
315 let buffer = hub.buffers.get(id);
316
317 unsafe { buffer.as_hal::<A>() }
318 }
319
320 pub unsafe fn texture_as_hal<A: hal::Api>(
324 &self,
325 id: TextureId,
326 ) -> Option<impl Deref<Target = A::Texture>> {
327 let hub = &self.hub;
328
329 let texture = hub.textures.get(id);
330
331 unsafe { texture.as_hal::<A>() }
332 }
333
334 pub unsafe fn texture_view_as_hal<A: hal::Api>(
338 &self,
339 id: TextureViewId,
340 ) -> Option<impl Deref<Target = A::TextureView>> {
341 let hub = &self.hub;
342
343 let view = hub.texture_views.get(id);
344
345 unsafe { view.as_hal::<A>() }
346 }
347
348 pub unsafe fn adapter_as_hal<A: hal::Api>(
352 &self,
353 id: AdapterId,
354 ) -> Option<impl Deref<Target = A::Adapter>> {
355 let hub = &self.hub;
356 let adapter = hub.adapters.get(id);
357
358 unsafe { adapter.as_hal::<A>() }
359 }
360
361 pub unsafe fn device_as_hal<A: hal::Api>(
365 &self,
366 id: DeviceId,
367 ) -> Option<impl Deref<Target = A::Device>> {
368 let device = self.hub.devices.get(id);
369
370 unsafe { device.as_hal::<A>() }
371 }
372
373 pub unsafe fn device_fence_as_hal<A: hal::Api>(
377 &self,
378 id: DeviceId,
379 ) -> Option<impl Deref<Target = A::Fence>> {
380 let device = self.hub.devices.get(id);
381
382 unsafe { device.fence_as_hal::<A>() }
383 }
384
385 pub unsafe fn surface_as_hal<A: hal::Api>(
389 &self,
390 id: SurfaceId,
391 ) -> Option<impl Deref<Target = A::Surface>> {
392 let surface = self.surfaces.get(id);
393
394 unsafe { surface.as_hal::<A>() }
395 }
396
397 pub unsafe fn command_encoder_as_hal_mut<
407 A: hal::Api,
408 F: FnOnce(Option<&mut A::CommandEncoder>) -> R,
409 R,
410 >(
411 &self,
412 id: CommandEncoderId,
413 hal_command_encoder_callback: F,
414 ) -> R {
415 let hub = &self.hub;
416
417 let cmd_enc = hub.command_encoders.get(id);
418 unsafe { cmd_enc.as_hal_mut::<A, F, R>(hal_command_encoder_callback) }
419 }
420
421 pub unsafe fn queue_as_hal<A: hal::Api>(
425 &self,
426 id: QueueId,
427 ) -> Option<impl Deref<Target = A::Queue>> {
428 let queue = self.hub.queues.get(id);
429
430 unsafe { queue.as_hal::<A>() }
431 }
432
433 pub unsafe fn blas_as_hal<A: hal::Api>(
437 &self,
438 id: BlasId,
439 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
440 profiling::scope!("Blas::as_hal");
441
442 let hub = &self.hub;
443
444 let blas = hub.blas_s.get(id);
445
446 unsafe { blas.as_hal::<A>() }
447 }
448
449 pub unsafe fn tlas_as_hal<A: hal::Api>(
453 &self,
454 id: TlasId,
455 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
456 profiling::scope!("Tlas::as_hal");
457
458 let hub = &self.hub;
459
460 let tlas = hub.tlas_s.get(id);
461
462 unsafe { tlas.as_hal::<A>() }
463 }
464}