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<
337 A: hal::Api,
338 F: FnOnce(Option<&mut A::CommandEncoder>) -> R,
339 R,
340 >(
341 &self,
342 id: CommandEncoderId,
343 hal_command_encoder_callback: F,
344 ) -> R {
345 profiling::scope!("CommandEncoder::as_hal");
346
347 let hub = &self.hub;
348
349 let cmd_enc = hub.command_encoders.get(id);
350 let mut cmd_buf_data = cmd_enc.data.lock();
351 cmd_buf_data.record_as_hal_mut(|opt_cmd_buf| -> R {
352 hal_command_encoder_callback(opt_cmd_buf.and_then(|cmd_buf| {
353 cmd_buf
354 .encoder
355 .open()
356 .ok()
357 .and_then(|encoder| encoder.as_any_mut().downcast_mut())
358 }))
359 })
360 }
361
362 pub unsafe fn queue_as_hal<A: hal::Api>(
366 &self,
367 id: QueueId,
368 ) -> Option<impl Deref<Target = A::Queue>> {
369 profiling::scope!("Queue::as_hal");
370
371 let queue = self.hub.queues.get(id);
372
373 SimpleResourceGuard::new(queue, move |queue| queue.raw().as_any().downcast_ref())
374 }
375
376 pub unsafe fn blas_as_hal<A: hal::Api>(
380 &self,
381 id: BlasId,
382 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
383 profiling::scope!("Blas::as_hal");
384
385 let hub = &self.hub;
386
387 let blas = hub.blas_s.get(id).get().ok()?;
388
389 SnatchableResourceGuard::new(blas)
390 }
391
392 pub unsafe fn tlas_as_hal<A: hal::Api>(
396 &self,
397 id: TlasId,
398 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
399 profiling::scope!("Tlas::as_hal");
400
401 let hub = &self.hub;
402
403 let tlas = hub.tlas_s.get(id).get().ok()?;
404
405 SnatchableResourceGuard::new(tlas)
406 }
407}