vulkayes_core/util/
handle.rs

1use std::{fmt, hash::Hash, ops::Deref};
2
3use ash::vk;
4
5use crate::util::{
6	sync::{Vutex, VutexGuard},
7	transparent::Transparent
8};
9
10/// Trait for objects that have corresponding Vulkan handles.
11pub trait HasHandle<T: vk::Handle + Copy>:
12	std::borrow::Borrow<T> + PartialEq + Eq + Hash + PartialOrd + Ord
13{
14	fn handle(&self) -> T {
15		*self.borrow()
16	}
17
18	/// Returns a safe handle borrowed from `self`.
19	fn safe_handle(&self) -> SafeHandle<T> {
20		unsafe { SafeHandle::from_raw(self.handle()) }
21	}
22}
23
24/// Wrapper around `VutexGuard` that can be borrowed as `SafeHandle`.
25pub struct VutexGuardSafeHandleBorrow<'a, T: vk::Handle> {
26	guard: VutexGuard<'a, T>
27}
28impl<'a, T: vk::Handle + Copy> VutexGuardSafeHandleBorrow<'a, T> {
29	/// ### Safety
30	///
31	/// `T` must be a valid handle for at least `'a`.
32	pub unsafe fn from_raw(guard: VutexGuard<'a, T>) -> Self {
33		Self { guard }
34	}
35
36	pub fn borrow_safe(&self) -> SafeHandle<'a, T> {
37		unsafe { SafeHandle::from_raw(*self.guard) }
38	}
39}
40impl<'a, T: vk::Handle> Deref for VutexGuardSafeHandleBorrow<'a, T> {
41	type Target = T;
42
43	fn deref(&self) -> &Self::Target {
44		self.guard.deref()
45	}
46}
47impl<'a, T: vk::Handle> Into<VutexGuard<'a, T>> for VutexGuardSafeHandleBorrow<'a, T> {
48	fn into(self) -> VutexGuard<'a, T> {
49		self.guard
50	}
51}
52
53/// Trait for objects that have corresponding Vulkan handles and are internally synchronized.
54pub trait HasSynchronizedHandle<T: vk::Handle + Copy>:
55	std::borrow::Borrow<Vutex<T>> + PartialEq + Eq + Hash + PartialOrd + Ord
56{
57	fn lock_handle(&self) -> VutexGuard<T> {
58		self.borrow().lock().expect("vutex poisoned")
59	}
60
61	fn lock_safe_handle(&self) -> VutexGuardSafeHandleBorrow<T> {
62		unsafe { VutexGuardSafeHandleBorrow::from_raw(self.lock_handle()) }
63	}
64}
65
66/// Wrapper struct around a handle that can only be safely obtained from a "smart" object and is guaranteed to be valid.
67#[repr(transparent)]
68#[derive(Copy, Clone, PartialEq, Eq, Hash)]
69pub struct SafeHandle<'a, T: ash::vk::Handle> {
70	handle: T,
71	ghost: std::marker::PhantomData<&'a T>
72}
73impl<'a, T: ash::vk::Handle> SafeHandle<'a, T> {
74	/// ### Safety
75	///
76	/// `handle` must be a valid handle for at least the lifetime `'a`.
77	pub unsafe fn from_raw(handle: T) -> Self {
78		SafeHandle {
79			handle,
80			ghost: std::marker::PhantomData
81		}
82	}
83
84	pub fn into_handle(self) -> T {
85		self.handle
86	}
87}
88impl<'a, T: ash::vk::Handle + Clone> SafeHandle<'a, T> {
89	/// ### Safety
90	///
91	/// `handle_ref` must be a reference to a valid handle for at least the lifetime `'a`.
92	pub unsafe fn from_raw_reference(handle_ref: &'a T) -> Self {
93		Self::from_raw(handle_ref.clone())
94	}
95}
96impl<'a, T: ash::vk::Handle> std::ops::Deref for SafeHandle<'a, T> {
97	type Target = T;
98
99	fn deref(&self) -> &Self::Target {
100		&self.handle
101	}
102}
103unsafe impl<'a, T: ash::vk::Handle> Transparent for SafeHandle<'a, T> {
104	type Target = T;
105}
106impl<'a, T: ash::vk::Handle + Copy> fmt::Debug for SafeHandle<'a, T> {
107	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108		write!(f, "{:?}", crate::util::fmt::format_handle(self.handle))
109	}
110}