1use {
7 crate::hal::Backend,
8 std::ops::{Deref, DerefMut},
9};
10
11#[cfg(not(feature = "no-slow-safety-checks"))]
12fn new_instance_id() -> InstanceId {
13 static INSTANCE_ID: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
14
15 let id = INSTANCE_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
16 assert!(
17 id < usize::max_value() && (id as u32) < u32::max_value(),
18 "Too many instances created"
19 );
20
21 if id == 0 {
22 log::info!("Slow safety checks are enabled! You can disable them in production by enabling the 'no-slow-safety-checks' feature!");
24 }
25
26 InstanceId { id: id as u32 }
27}
28
29#[cfg(not(feature = "no-slow-safety-checks"))]
30fn new_device_id(instance: InstanceId) -> DeviceId {
31 static DEVICE_ID: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
32
33 let id = DEVICE_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
34 assert!(
35 id < usize::max_value() && (id as u32) < u32::max_value(),
36 "Too many devices created"
37 );
38
39 DeviceId {
40 id: id as u32,
41 instance,
42 }
43}
44
45#[cfg(feature = "no-slow-safety-checks")]
46fn new_instance_id() -> InstanceId {
47 InstanceId {}
48}
49
50#[cfg(feature = "no-slow-safety-checks")]
51fn new_device_id(instance: InstanceId) -> DeviceId {
52 DeviceId { instance }
53}
54
55#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
57pub struct InstanceId {
58 #[cfg(not(feature = "no-slow-safety-checks"))]
60 pub id: u32,
61}
62
63impl InstanceId {
64 pub fn new() -> Self {
66 new_instance_id()
67 }
68}
69
70pub struct Instance<B: Backend> {
72 instance: B::Instance,
73 id: InstanceId,
74}
75
76impl<B> Instance<B>
77where
78 B: Backend,
79{
80 pub fn new(instance: B::Instance) -> Self {
82 Instance {
83 id: new_instance_id(),
84 instance,
85 }
86 }
87
88 pub unsafe fn from_raw(instance: B::Instance, id: InstanceId) -> Self {
90 Instance { id, instance }
91 }
92
93 pub fn id(&self) -> InstanceId {
95 self.id
96 }
97
98 pub fn raw(&self) -> &B::Instance {
100 &self.instance
101 }
102
103 pub fn raw_mut(&mut self) -> &mut B::Instance {
105 &mut self.instance
106 }
107
108 pub fn into_raw(self) -> B::Instance {
110 self.instance
111 }
112}
113
114impl<B> Deref for Instance<B>
115where
116 B: Backend,
117{
118 type Target = B::Instance;
119
120 fn deref(&self) -> &B::Instance {
121 self.raw()
122 }
123}
124
125impl<B> DerefMut for Instance<B>
126where
127 B: Backend,
128{
129 fn deref_mut(&mut self) -> &mut B::Instance {
130 self.raw_mut()
131 }
132}
133
134impl<B> std::fmt::Debug for Instance<B>
135where
136 B: Backend,
137{
138 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 write!(fmt, "Instance {:?}", self.id)
140 }
141}
142
143#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
145pub struct DeviceId {
146 #[cfg(not(feature = "no-slow-safety-checks"))]
148 pub id: u32,
149
150 pub instance: InstanceId,
152}
153
154impl DeviceId {
155 pub fn new(instance: InstanceId) -> Self {
157 new_device_id(instance)
158 }
159}
160
161#[derive(Debug)]
163pub struct Device<B: Backend> {
164 device: B::Device,
165 id: DeviceId,
166}
167
168impl<B> Device<B>
169where
170 B: Backend,
171{
172 pub fn new(device: B::Device, instance: &Instance<B>) -> Self {
174 Device {
175 id: new_device_id(instance.id),
176 device,
177 }
178 }
179
180 pub fn from_raw(device: B::Device, id: DeviceId) -> Self {
182 Device { id, device }
183 }
184
185 pub fn id(&self) -> DeviceId {
187 self.id
188 }
189
190 pub fn raw(&self) -> &B::Device {
192 &self.device
193 }
194
195 pub fn raw_mut(&mut self) -> &mut B::Device {
197 &mut self.device
198 }
199
200 pub fn into_raw(self) -> B::Device {
202 self.device
203 }
204}
205
206impl<B> Deref for Device<B>
207where
208 B: Backend,
209{
210 type Target = B::Device;
211
212 fn deref(&self) -> &B::Device {
213 self.raw()
214 }
215}
216
217#[macro_export]
219macro_rules! device_owned {
220 ($type:ident<B $(, $arg:ident $(: $(?$sized:ident)? $($bound:path)?)?)*> @ $getter:expr) => {
221 #[allow(unused_qualifications)]
222 impl<B $(, $arg)*> $type<B $(, $arg)*>
223 where
224 B: $crate::hal::Backend,
225 $(
226 $($arg: $(?$sized)* $($bound)?,)?
227 )*
228 {
229 pub fn device_id(&self) -> $crate::DeviceId {
231 ($getter)(self)
232 }
233
234 pub fn assert_device_owner(&self, device: &$crate::Device<B>) {
236 assert_eq!(self.device_id(), device.id(), "Resource is not owned by specified device");
237 }
238
239 pub fn instance_id(&self) -> $crate::InstanceId {
241 self.device_id().instance
242 }
243
244 pub fn assert_instance_owner(&self, instance: &$crate::Instance<B>) {
246 assert_eq!(self.instance_id(), instance.id(), "Resource is not owned by specified instance");
247 }
248 }
249 };
250
251 ($type:ident<B $(, $arg:ident $(: $(?$sized:ident)? $($bound:path)?)?)*>) => {
252 device_owned!($type<B $(, $arg $(: $(?$sized)? $($bound)?)?)*> @ (|s: &Self| {s.device}));
253 };
254}
255
256#[macro_export]
258macro_rules! instance_owned {
259 ($type:ident<B $(, $arg:ident $(: $(?$sized:ident)? $($bound:path)?)?)*>) => {
260 #[allow(unused_qualifications)]
261 impl<B $(, $arg)*> $type<B $(, $arg)*>
262 where
263 B: $crate::hal::Backend,
264 $(
265 $($arg: $(?$sized)? $($bound)?,)?
266 )*
267 {
268 pub fn instance_id(&self) -> $crate::InstanceId {
270 self.instance
271 }
272
273 pub fn assert_instance_owner(&self, instance: &Instance<B>) {
275 assert_eq!(self.instance_id(), instance.id());
276 }
277 }
278 };
279}