bedrock/
ext.rs

1//! Extension Helper
2
3use std::iter::FusedIterator;
4
5#[repr(C)]
6#[allow(non_snake_case)]
7pub struct GenericVulkanStructure {
8    pub sType: crate::vk::VkStructureType,
9    pub pNext: *const core::ffi::c_void,
10    pub _rest: [u8; 0],
11}
12impl GenericVulkanStructure {
13    pub const unsafe fn cast_unchecked<T>(&self) -> &T {
14        unsafe { core::mem::transmute(self) }
15    }
16}
17
18pub unsafe trait VulkanStructure {
19    /// Cast structure ref to generic. This is same as transmute but must be safe.
20    fn as_generic(&self) -> &GenericVulkanStructure;
21
22    /// Cast structure mutable ref to generic. This is same as transmute but must be safe.
23    fn as_generic_mut(&mut self) -> &mut GenericVulkanStructure;
24}
25pub unsafe trait TypedVulkanStructure: VulkanStructure + Sized {
26    /// sType of this structure
27    const TYPE: crate::vk::VkStructureType;
28
29    /// Cast structure ref only if sType matches
30    fn try_from_generic(g: &GenericVulkanStructure) -> Option<&Self> {
31        if g.sType == Self::TYPE {
32            Some(unsafe { g.cast_unchecked() })
33        } else {
34            None
35        }
36    }
37}
38unsafe impl<S: VulkanStructure + ?Sized> VulkanStructure for &'_ mut S {
39    fn as_generic(&self) -> &GenericVulkanStructure {
40        S::as_generic(*self)
41    }
42
43    fn as_generic_mut(&mut self) -> &mut GenericVulkanStructure {
44        S::as_generic_mut(*self)
45    }
46}
47unsafe impl<S: TypedVulkanStructure + ?Sized> TypedVulkanStructure for &'_ mut S {
48    const TYPE: crate::vk::VkStructureType = S::TYPE;
49}
50unsafe impl<S: VulkanStructure + ?Sized> VulkanStructure for Box<S> {
51    fn as_generic(&self) -> &GenericVulkanStructure {
52        S::as_generic(&**self)
53    }
54
55    fn as_generic_mut(&mut self) -> &mut GenericVulkanStructure {
56        S::as_generic_mut(&mut **self)
57    }
58}
59unsafe impl<S: TypedVulkanStructure + ?Sized> TypedVulkanStructure for Box<S> {
60    const TYPE: crate::vk::VkStructureType = S::TYPE;
61}
62
63#[repr(C)]
64#[allow(non_snake_case)]
65pub struct GenericVulkanSinkStructure {
66    pub sType: crate::vk::VkStructureType,
67    pub pNext: *mut core::ffi::c_void,
68    _rest: [u8; 0],
69}
70impl GenericVulkanSinkStructure {
71    pub const unsafe fn cast_ref_unchecked<T>(&self) -> &T {
72        unsafe { core::mem::transmute(self) }
73    }
74
75    pub const unsafe fn cast_mut_unchecked<T>(&mut self) -> &mut T {
76        unsafe { core::mem::transmute(self) }
77    }
78}
79
80pub unsafe trait VulkanSinkStructure {
81    /// Cast this structure ref to generic one. This is same as transmute but must be safe.
82    fn as_generic(&self) -> &GenericVulkanSinkStructure;
83
84    /// Cast this structure mutable ref to generic one. This is same as transmute but must be safe.
85    fn as_generic_mut(&mut self) -> &mut GenericVulkanSinkStructure;
86}
87pub unsafe trait TypedVulkanSinkStructure: VulkanSinkStructure + Sized {
88    /// `sType` constant for this structure.
89    const TYPE: crate::vk::VkStructureType;
90
91    /// Constructs an uninitialized cell for this structure, that is ready to pass the api
92    fn uninit_sink() -> core::mem::MaybeUninit<Self> {
93        let mut p = core::mem::MaybeUninit::<Self>::uninit();
94        unsafe {
95            let ptr = p.as_mut_ptr() as *mut GenericVulkanSinkStructure;
96            core::ptr::addr_of_mut!((*ptr).sType).write(Self::TYPE);
97            core::ptr::addr_of_mut!((*ptr).pNext).write(core::ptr::null_mut());
98        }
99
100        p
101    }
102
103    /// Cast structure ref only if sType matches
104    fn try_from_generic(g: &GenericVulkanSinkStructure) -> Option<&Self> {
105        if g.sType == Self::TYPE {
106            Some(unsafe { g.cast_ref_unchecked() })
107        } else {
108            None
109        }
110    }
111}
112unsafe impl<T> VulkanSinkStructure for &'_ mut T
113where
114    T: VulkanSinkStructure,
115{
116    #[inline(always)]
117    fn as_generic(&self) -> &GenericVulkanSinkStructure {
118        T::as_generic(*self)
119    }
120
121    #[inline(always)]
122    fn as_generic_mut(&mut self) -> &mut GenericVulkanSinkStructure {
123        T::as_generic_mut(*self)
124    }
125}
126unsafe impl<T> TypedVulkanSinkStructure for &'_ mut T
127where
128    T: TypedVulkanSinkStructure,
129{
130    const TYPE: crate::vk::VkStructureType = T::TYPE;
131}
132unsafe impl<T> VulkanSinkStructure for Box<T>
133where
134    T: VulkanSinkStructure + ?Sized,
135{
136    #[inline(always)]
137    fn as_generic(&self) -> &GenericVulkanSinkStructure {
138        T::as_generic(&*self)
139    }
140
141    #[inline(always)]
142    fn as_generic_mut(&mut self) -> &mut GenericVulkanSinkStructure {
143        T::as_generic_mut(&mut *self)
144    }
145}
146unsafe impl<T> TypedVulkanSinkStructure for Box<T>
147where
148    T: TypedVulkanSinkStructure,
149{
150    const TYPE: crate::vk::VkStructureType = T::TYPE;
151}
152
153pub struct StructureChainIterator<'a> {
154    pub(crate) current: *const GenericVulkanStructure,
155    pub(crate) marker: std::marker::PhantomData<&'a GenericVulkanStructure>,
156}
157impl<'a> Iterator for StructureChainIterator<'a> {
158    type Item = &'a GenericVulkanStructure;
159    fn next(&mut self) -> Option<&'a GenericVulkanStructure> {
160        if let Some(r) = unsafe { self.current.as_ref() } {
161            self.current = r.pNext as _;
162            unsafe { self.current.as_ref() }
163        } else {
164            None
165        }
166    }
167}
168impl FusedIterator for StructureChainIterator<'_> {}
169
170pub struct SinkStructureChainIterator<'a> {
171    pub(crate) current: *const GenericVulkanSinkStructure,
172    pub(crate) marker: core::marker::PhantomData<&'a GenericVulkanSinkStructure>,
173}
174impl<'a> Iterator for SinkStructureChainIterator<'a> {
175    type Item = &'a GenericVulkanSinkStructure;
176
177    fn next(&mut self) -> Option<&'a GenericVulkanSinkStructure> {
178        let Some(r) = (unsafe { self.current.as_ref() }) else {
179            return None;
180        };
181
182        self.current = r.pNext as _;
183        unsafe { self.current.as_ref() }
184    }
185}
186impl FusedIterator for SinkStructureChainIterator<'_> {}
187
188pub trait VulkanStructureProvider {
189    type RootStructure;
190
191    fn build<'r, 's: 'r>(&'s mut self, root: &'s mut Self::RootStructure) -> &'r mut GenericVulkanStructure;
192}
193pub struct Extends<Parent: VulkanStructureProvider, T>(pub(crate) Parent, pub(crate) T);
194impl<Parent: VulkanStructureProvider, T> VulkanStructureProvider for Extends<Parent, T>
195where
196    T: TypedVulkanStructure,
197{
198    type RootStructure = Parent::RootStructure;
199
200    fn build<'r, 's: 'r>(&'s mut self, root: &'s mut Self::RootStructure) -> &'r mut GenericVulkanStructure {
201        let parent = self.0.build(root);
202        parent.pNext = &self.1 as *const _ as _;
203        self.1.as_generic_mut()
204    }
205}
206pub trait Extendable<T>: Sized + VulkanStructureProvider {
207    #[inline]
208    fn extends(self, next: T) -> Extends<Self, T> {
209        Extends(self, next)
210    }
211}
212
213pub unsafe trait UninitVulkanStructureOps {
214    fn set_next(&mut self, next: &(impl TypedVulkanStructure + ?Sized));
215}
216unsafe impl<T> UninitVulkanStructureOps for core::mem::MaybeUninit<T>
217where
218    T: TypedVulkanStructure,
219{
220    #[inline(always)]
221    fn set_next(&mut self, next: &(impl TypedVulkanStructure + ?Sized)) {
222        let p = self.as_mut_ptr() as *mut GenericVulkanStructure;
223        unsafe {
224            core::ptr::addr_of_mut!((*p).pNext).write(next.as_generic() as *const _ as _);
225        }
226    }
227}
228
229pub trait Chainable<'d, T> {
230    fn chain(&mut self, next: &'d T) -> &mut Self;
231}
232
233pub trait StructureChainQuery {
234    /// Iterate pNext chain
235    fn iter_chain(&self) -> StructureChainIterator;
236
237    fn query_structure_type(&self, ty: crate::vk::VkStructureType) -> Option<&GenericVulkanStructure> {
238        self.iter_chain().find(|s| s.sType == ty)
239    }
240    fn query_structure<S: TypedVulkanStructure>(&self) -> Option<&S> {
241        self.query_structure_type(S::TYPE)
242            .map(|r| unsafe { r.cast_unchecked() })
243    }
244}
245impl<S: TypedVulkanStructure> StructureChainQuery for S {
246    #[inline(always)]
247    fn iter_chain(&self) -> StructureChainIterator {
248        StructureChainIterator {
249            current: self.as_generic() as _,
250            marker: std::marker::PhantomData,
251        }
252    }
253}
254
255pub trait SinkStructureChainQuery {
256    /// Iterate pNext chain
257    fn iter_chain(&self) -> SinkStructureChainIterator;
258
259    #[inline(always)]
260    fn query_structure_type(&self, ty: crate::vk::VkStructureType) -> Option<&GenericVulkanSinkStructure> {
261        self.iter_chain().find(|s| s.sType == ty)
262    }
263
264    #[inline(always)]
265    fn query_structure<S: TypedVulkanSinkStructure>(&self) -> Option<&S> {
266        self.query_structure_type(S::TYPE)
267            .map(|r| unsafe { r.cast_ref_unchecked() })
268    }
269}
270impl<S: TypedVulkanSinkStructure> SinkStructureChainQuery for S {
271    #[inline(always)]
272    fn iter_chain(&self) -> SinkStructureChainIterator {
273        SinkStructureChainIterator {
274            current: self.as_generic() as _,
275            marker: core::marker::PhantomData,
276        }
277    }
278}