1use core::{mem::ManuallyDrop, ops::Deref};
2
3use alloc::sync::Arc;
4use hal::DynResource;
5
6use crate::{lock::RankData, resource::RawResourceAccess, snatch::SnatchGuard};
7
8struct SimpleResourceGuard<Resource, HalType> {
10 _guard: Resource,
11 ptr: *const HalType,
12}
13
14impl<Resource, HalType> SimpleResourceGuard<Resource, HalType> {
15 pub fn new<C>(guard: Resource, callback: C) -> Option<Self>
17 where
18 C: Fn(&Resource) -> Option<&HalType>,
19 {
20 let ptr: *const HalType = callback(&guard)?;
22
23 Some(Self { _guard: guard, ptr })
24 }
25}
26
27impl<Resource, HalType> Deref for SimpleResourceGuard<Resource, HalType> {
28 type Target = HalType;
29
30 fn deref(&self) -> &Self::Target {
31 unsafe { &*self.ptr }
34 }
35}
36
37unsafe impl<Resource, HalType> Send for SimpleResourceGuard<Resource, HalType>
38where
39 Resource: Send,
40 HalType: Send,
41{
42}
43unsafe impl<Resource, HalType> Sync for SimpleResourceGuard<Resource, HalType>
44where
45 Resource: Sync,
46 HalType: Sync,
47{
48}
49
50struct SnatchableResourceGuard<Resource, HalType>
52where
53 Resource: RawResourceAccess,
54{
55 resource: Arc<Resource>,
56 snatch_lock_rank_data: ManuallyDrop<RankData>,
57 ptr: *const HalType,
58}
59
60impl<Resource, HalType> SnatchableResourceGuard<Resource, HalType>
61where
62 Resource: RawResourceAccess,
63 HalType: 'static,
64{
65 pub fn new(resource: Arc<Resource>) -> Option<Self> {
71 let snatch_guard = resource.device().snatchable_lock.read();
73
74 let underlying = resource
76 .raw(&snatch_guard)?
77 .as_any()
78 .downcast_ref::<HalType>()?;
79
80 let ptr: *const HalType = underlying;
83
84 let snatch_lock_rank_data = SnatchGuard::forget(snatch_guard);
87
88 Some(Self {
91 resource,
92 snatch_lock_rank_data: ManuallyDrop::new(snatch_lock_rank_data),
93 ptr,
94 })
95 }
96}
97
98impl<Resource, HalType> Deref for SnatchableResourceGuard<Resource, HalType>
99where
100 Resource: RawResourceAccess,
101{
102 type Target = HalType;
103
104 fn deref(&self) -> &Self::Target {
105 unsafe { &*self.ptr }
109 }
110}
111
112impl<Resource, HalType> Drop for SnatchableResourceGuard<Resource, HalType>
113where
114 Resource: RawResourceAccess,
115{
116 fn drop(&mut self) {
117 let data = unsafe { ManuallyDrop::take(&mut self.snatch_lock_rank_data) };
120
121 unsafe {
126 self.resource
127 .device()
128 .snatchable_lock
129 .force_unlock_read(data)
130 };
131 }
132}
133
134unsafe impl<Resource, HalType> Send for SnatchableResourceGuard<Resource, HalType>
135where
136 Resource: RawResourceAccess + Send,
137 HalType: Send,
138{
139}
140unsafe impl<Resource, HalType> Sync for SnatchableResourceGuard<Resource, HalType>
141where
142 Resource: RawResourceAccess + Sync,
143 HalType: Sync,
144{
145}
146
147impl crate::resource::Buffer {
148 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Buffer>> {
152 profiling::scope!("Buffer::as_hal");
153
154 SnatchableResourceGuard::new(self)
155 }
156}
157
158impl crate::resource::Texture {
159 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Texture>> {
163 profiling::scope!("Texture::as_hal");
164
165 SnatchableResourceGuard::new(self)
166 }
167}
168
169impl crate::resource::TextureView {
170 pub unsafe fn as_hal<A: hal::Api>(
174 self: Arc<Self>,
175 ) -> Option<impl Deref<Target = A::TextureView>> {
176 profiling::scope!("TextureView::as_hal");
177
178 SnatchableResourceGuard::new(self)
179 }
180}
181
182impl crate::instance::Adapter {
183 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Adapter>> {
187 profiling::scope!("Adapter::as_hal");
188
189 SimpleResourceGuard::new(self, move |adapter| {
190 adapter.raw.adapter.as_any().downcast_ref()
191 })
192 }
193}
194
195impl crate::device::Device {
196 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Device>> {
200 profiling::scope!("Device::as_hal");
201
202 SimpleResourceGuard::new(self, move |device| device.raw().as_any().downcast_ref())
203 }
204
205 pub unsafe fn fence_as_hal<A: hal::Api>(
209 self: Arc<Self>,
210 ) -> Option<impl Deref<Target = A::Fence>> {
211 profiling::scope!("Device::fence_as_hal");
212
213 SimpleResourceGuard::new(self, move |device| device.fence.as_any().downcast_ref())
214 }
215}
216
217impl crate::instance::Surface {
218 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Surface>> {
222 profiling::scope!("Surface::as_hal");
223
224 SimpleResourceGuard::new(self, move |surface| {
225 surface.raw(A::VARIANT)?.as_any().downcast_ref()
226 })
227 }
228}
229
230impl crate::command::CommandEncoder {
231 pub unsafe fn as_hal_mut<A: hal::Api, F: FnOnce(Option<&mut A::CommandEncoder>) -> R, R>(
241 self: &Arc<Self>,
242 hal_command_encoder_callback: F,
243 ) -> R {
244 profiling::scope!("CommandEncoder::as_hal");
245
246 let mut cmd_buf_data = self.data.lock();
247 cmd_buf_data.record_as_hal_mut(|opt_cmd_buf| -> R {
248 hal_command_encoder_callback(opt_cmd_buf.and_then(|cmd_buf| {
249 cmd_buf
250 .encoder
251 .open()
252 .ok()
253 .and_then(|encoder| encoder.as_any_mut().downcast_mut())
254 }))
255 })
256 }
257}
258
259impl crate::device::queue::Queue {
260 pub unsafe fn as_hal<A: hal::Api>(self: Arc<Self>) -> Option<impl Deref<Target = A::Queue>> {
264 profiling::scope!("Queue::as_hal");
265
266 SimpleResourceGuard::new(self, move |queue| queue.raw().as_any().downcast_ref())
267 }
268}
269
270impl crate::resource::Blas {
271 pub unsafe fn as_hal<A: hal::Api>(
275 self: Arc<Self>,
276 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
277 profiling::scope!("Blas::as_hal");
278
279 SnatchableResourceGuard::new(self)
280 }
281}
282
283impl crate::resource::Tlas {
284 pub unsafe fn as_hal<A: hal::Api>(
288 self: Arc<Self>,
289 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
290 profiling::scope!("Tlas::as_hal");
291
292 SnatchableResourceGuard::new(self)
293 }
294}