1use core::{mem::ManuallyDrop, ops::Deref};
2
3use alloc::sync::Arc;
4use hal::DynResource;
5
6use crate::{
7 device::Device,
8 global::Global,
9 id::{
10 AdapterId, BlasId, BufferId, CommandEncoderId, DeviceId, QueueId, SurfaceId, TextureId,
11 TextureViewId, TlasId,
12 },
13 lock::{RankData, RwLockReadGuard},
14 resource::RawResourceAccess,
15 snatch::SnatchGuard,
16};
17
18struct SimpleResourceGuard<Resource, HalType> {
20 _guard: Resource,
21 ptr: *const HalType,
22}
23
24impl<Resource, HalType> SimpleResourceGuard<Resource, HalType> {
25 pub fn new<C>(guard: Resource, callback: C) -> Option<Self>
27 where
28 C: Fn(&Resource) -> Option<&HalType>,
29 {
30 let ptr: *const HalType = callback(&guard)?;
32
33 Some(Self { _guard: guard, ptr })
34 }
35}
36
37impl<Resource, HalType> Deref for SimpleResourceGuard<Resource, HalType> {
38 type Target = HalType;
39
40 fn deref(&self) -> &Self::Target {
41 unsafe { &*self.ptr }
44 }
45}
46
47unsafe impl<Resource, HalType> Send for SimpleResourceGuard<Resource, HalType>
48where
49 Resource: Send,
50 HalType: Send,
51{
52}
53unsafe impl<Resource, HalType> Sync for SimpleResourceGuard<Resource, HalType>
54where
55 Resource: Sync,
56 HalType: Sync,
57{
58}
59
60struct SnatchableResourceGuard<Resource, HalType>
62where
63 Resource: RawResourceAccess,
64{
65 resource: Arc<Resource>,
66 snatch_lock_rank_data: ManuallyDrop<RankData>,
67 ptr: *const HalType,
68}
69
70impl<Resource, HalType> SnatchableResourceGuard<Resource, HalType>
71where
72 Resource: RawResourceAccess,
73 HalType: 'static,
74{
75 pub fn new(resource: Arc<Resource>) -> Option<Self> {
81 let snatch_guard = resource.device().snatchable_lock.read();
83
84 let underlying = resource
86 .raw(&snatch_guard)?
87 .as_any()
88 .downcast_ref::<HalType>()?;
89
90 let ptr: *const HalType = underlying;
93
94 let snatch_lock_rank_data = SnatchGuard::forget(snatch_guard);
97
98 Some(Self {
101 resource,
102 snatch_lock_rank_data: ManuallyDrop::new(snatch_lock_rank_data),
103 ptr,
104 })
105 }
106}
107
108impl<Resource, HalType> Deref for SnatchableResourceGuard<Resource, HalType>
109where
110 Resource: RawResourceAccess,
111{
112 type Target = HalType;
113
114 fn deref(&self) -> &Self::Target {
115 unsafe { &*self.ptr }
119 }
120}
121
122impl<Resource, HalType> Drop for SnatchableResourceGuard<Resource, HalType>
123where
124 Resource: RawResourceAccess,
125{
126 fn drop(&mut self) {
127 let data = unsafe { ManuallyDrop::take(&mut self.snatch_lock_rank_data) };
130
131 unsafe {
136 self.resource
137 .device()
138 .snatchable_lock
139 .force_unlock_read(data)
140 };
141 }
142}
143
144unsafe impl<Resource, HalType> Send for SnatchableResourceGuard<Resource, HalType>
145where
146 Resource: RawResourceAccess + Send,
147 HalType: Send,
148{
149}
150unsafe impl<Resource, HalType> Sync for SnatchableResourceGuard<Resource, HalType>
151where
152 Resource: RawResourceAccess + Sync,
153 HalType: Sync,
154{
155}
156
157struct FenceGuard<Fence> {
159 device: Arc<Device>,
160 fence_lock_rank_data: ManuallyDrop<RankData>,
161 ptr: *const Fence,
162}
163
164impl<Fence> FenceGuard<Fence>
165where
166 Fence: 'static,
167{
168 pub fn new(device: Arc<Device>) -> Option<Self> {
173 let fence_guard = device.fence.read();
175
176 let ptr: *const Fence = fence_guard.as_any().downcast_ref::<Fence>()?;
179
180 let fence_lock_rank_data = RwLockReadGuard::forget(fence_guard);
183
184 Some(Self {
187 device,
188 fence_lock_rank_data: ManuallyDrop::new(fence_lock_rank_data),
189 ptr,
190 })
191 }
192}
193
194impl<Fence> Deref for FenceGuard<Fence> {
195 type Target = Fence;
196
197 fn deref(&self) -> &Self::Target {
198 unsafe { &*self.ptr }
202 }
203}
204
205impl<Fence> Drop for FenceGuard<Fence> {
206 fn drop(&mut self) {
207 let data = unsafe { ManuallyDrop::take(&mut self.fence_lock_rank_data) };
210
211 unsafe {
216 self.device.fence.force_unlock_read(data);
217 };
218 }
219}
220
221unsafe impl<Fence> Send for FenceGuard<Fence> where Fence: Send {}
222unsafe impl<Fence> Sync for FenceGuard<Fence> where Fence: Sync {}
223
224impl Global {
225 pub unsafe fn buffer_as_hal<A: hal::Api>(
229 &self,
230 id: BufferId,
231 ) -> Option<impl Deref<Target = A::Buffer>> {
232 profiling::scope!("Buffer::as_hal");
233
234 let hub = &self.hub;
235
236 let buffer = hub.buffers.get(id).get().ok()?;
237
238 SnatchableResourceGuard::new(buffer)
239 }
240
241 pub unsafe fn texture_as_hal<A: hal::Api>(
245 &self,
246 id: TextureId,
247 ) -> Option<impl Deref<Target = A::Texture>> {
248 profiling::scope!("Texture::as_hal");
249
250 let hub = &self.hub;
251
252 let texture = hub.textures.get(id).get().ok()?;
253
254 SnatchableResourceGuard::new(texture)
255 }
256
257 pub unsafe fn texture_view_as_hal<A: hal::Api>(
261 &self,
262 id: TextureViewId,
263 ) -> Option<impl Deref<Target = A::TextureView>> {
264 profiling::scope!("TextureView::as_hal");
265
266 let hub = &self.hub;
267
268 let view = hub.texture_views.get(id).get().ok()?;
269
270 SnatchableResourceGuard::new(view)
271 }
272
273 pub unsafe fn adapter_as_hal<A: hal::Api>(
277 &self,
278 id: AdapterId,
279 ) -> Option<impl Deref<Target = A::Adapter>> {
280 profiling::scope!("Adapter::as_hal");
281
282 let hub = &self.hub;
283 let adapter = hub.adapters.get(id);
284
285 SimpleResourceGuard::new(adapter, move |adapter| {
286 adapter.raw.adapter.as_any().downcast_ref()
287 })
288 }
289
290 pub unsafe fn device_as_hal<A: hal::Api>(
294 &self,
295 id: DeviceId,
296 ) -> Option<impl Deref<Target = A::Device>> {
297 profiling::scope!("Device::as_hal");
298
299 let device = self.hub.devices.get(id);
300
301 SimpleResourceGuard::new(device, move |device| device.raw().as_any().downcast_ref())
302 }
303
304 pub unsafe fn device_fence_as_hal<A: hal::Api>(
308 &self,
309 id: DeviceId,
310 ) -> Option<impl Deref<Target = A::Fence>> {
311 profiling::scope!("Device::fence_as_hal");
312
313 let device = self.hub.devices.get(id);
314
315 FenceGuard::new(device)
316 }
317
318 pub unsafe fn surface_as_hal<A: hal::Api>(
321 &self,
322 id: SurfaceId,
323 ) -> Option<impl Deref<Target = A::Surface>> {
324 profiling::scope!("Surface::as_hal");
325
326 let surface = self.surfaces.get(id);
327
328 SimpleResourceGuard::new(surface, move |surface| {
329 surface.raw(A::VARIANT)?.as_any().downcast_ref()
330 })
331 }
332
333 pub unsafe fn command_encoder_as_hal_mut<
343 A: hal::Api,
344 F: FnOnce(Option<&mut A::CommandEncoder>) -> R,
345 R,
346 >(
347 &self,
348 id: CommandEncoderId,
349 hal_command_encoder_callback: F,
350 ) -> R {
351 profiling::scope!("CommandEncoder::as_hal");
352
353 let hub = &self.hub;
354
355 let cmd_enc = hub.command_encoders.get(id);
356 let mut cmd_buf_data = cmd_enc.data.lock();
357 cmd_buf_data.record_as_hal_mut(|opt_cmd_buf| -> R {
358 hal_command_encoder_callback(opt_cmd_buf.and_then(|cmd_buf| {
359 cmd_buf
360 .encoder
361 .open()
362 .ok()
363 .and_then(|encoder| encoder.as_any_mut().downcast_mut())
364 }))
365 })
366 }
367
368 pub unsafe fn queue_as_hal<A: hal::Api>(
372 &self,
373 id: QueueId,
374 ) -> Option<impl Deref<Target = A::Queue>> {
375 profiling::scope!("Queue::as_hal");
376
377 let queue = self.hub.queues.get(id);
378
379 SimpleResourceGuard::new(queue, move |queue| queue.raw().as_any().downcast_ref())
380 }
381
382 pub unsafe fn blas_as_hal<A: hal::Api>(
386 &self,
387 id: BlasId,
388 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
389 profiling::scope!("Blas::as_hal");
390
391 let hub = &self.hub;
392
393 let blas = hub.blas_s.get(id).get().ok()?;
394
395 SnatchableResourceGuard::new(blas)
396 }
397
398 pub unsafe fn tlas_as_hal<A: hal::Api>(
402 &self,
403 id: TlasId,
404 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
405 profiling::scope!("Tlas::as_hal");
406
407 let hub = &self.hub;
408
409 let tlas = hub.tlas_s.get(id).get().ok()?;
410
411 SnatchableResourceGuard::new(tlas)
412 }
413}