Skip to main content

bedrock/
ext.rs

1//! Extension Helper
2use bedrock_vk as brvk;
3
4use std::iter::FusedIterator;
5
6#[inline(always)]
7pub const fn uninit_sink<T: brvk::TypedVulkanSinkStructure>() -> core::mem::MaybeUninit<T> {
8    let mut p = core::mem::MaybeUninit::<T>::uninit();
9    unsafe {
10        core::ptr::addr_of_mut!((*p.as_mut_ptr().cast::<brvk::GenericVulkanSinkStructure>()).sType).write(T::TYPE);
11        core::ptr::addr_of_mut!((*p.as_mut_ptr().cast::<brvk::GenericVulkanSinkStructure>()).pNext)
12            .write(core::ptr::null_mut());
13    }
14
15    p
16}
17
18pub struct StructureChainIterator<'a> {
19    pub(crate) current: *const brvk::GenericVulkanStructure,
20    pub(crate) marker: std::marker::PhantomData<&'a brvk::GenericVulkanStructure>,
21}
22impl<'a> Iterator for StructureChainIterator<'a> {
23    type Item = &'a brvk::GenericVulkanStructure;
24    fn next(&mut self) -> Option<&'a brvk::GenericVulkanStructure> {
25        if let Some(r) = unsafe { self.current.as_ref() } {
26            self.current = r.pNext as _;
27            unsafe { self.current.as_ref() }
28        } else {
29            None
30        }
31    }
32}
33impl FusedIterator for StructureChainIterator<'_> {}
34
35pub struct SinkStructureChainIterator<'a> {
36    pub(crate) current: *const brvk::GenericVulkanSinkStructure,
37    pub(crate) marker: core::marker::PhantomData<&'a brvk::GenericVulkanSinkStructure>,
38}
39impl<'a> Iterator for SinkStructureChainIterator<'a> {
40    type Item = &'a brvk::GenericVulkanSinkStructure;
41
42    fn next(&mut self) -> Option<&'a brvk::GenericVulkanSinkStructure> {
43        self.current = unsafe { self.current.as_ref() }?.pNext.cast();
44        unsafe { self.current.as_ref() }
45    }
46}
47impl FusedIterator for SinkStructureChainIterator<'_> {}
48
49pub trait VulkanStructureProvider {
50    type RootStructure;
51
52    fn build<'r, 's: 'r>(&'s mut self, root: &'s mut Self::RootStructure) -> &'r mut brvk::GenericVulkanStructure;
53}
54pub struct Extends<Parent: VulkanStructureProvider, T>(pub(crate) Parent, pub(crate) T);
55impl<Parent: VulkanStructureProvider, T> VulkanStructureProvider for Extends<Parent, T>
56where
57    T: brvk::TypedVulkanStructure,
58{
59    type RootStructure = Parent::RootStructure;
60
61    fn build<'r, 's: 'r>(&'s mut self, root: &'s mut Self::RootStructure) -> &'r mut brvk::GenericVulkanStructure {
62        let parent = self.0.build(root);
63        parent.pNext = &self.1 as *const _ as _;
64        self.1.as_generic_mut()
65    }
66}
67pub trait Extendable<T>: Sized + VulkanStructureProvider {
68    #[inline]
69    fn extends(self, next: T) -> Extends<Self, T> {
70        Extends(self, next)
71    }
72}
73
74// pub unsafe trait Uninitbrvk::VulkanStructureOps {
75//     fn set_next(&mut self, next: &(impl brvk::TypedVulkanStructure + ?Sized));
76// }
77// unsafe impl<T> Uninitbrvk::VulkanStructureOps for core::mem::MaybeUninit<T>
78// where
79//     T: brvk::TypedVulkanStructure,
80// {
81//     #[inline(always)]
82//     fn set_next(&mut self, next: &(impl brvk::TypedVulkanStructure + ?Sized)) {
83//         let p = self.as_mut_ptr() as *mut brvk::GenericVulkanStructure;
84//         unsafe {
85//             core::ptr::addr_of_mut!((*p).pNext).write(next.as_generic() as *const _ as _);
86//         }
87//     }
88// }
89
90pub trait Chainable<'d, T> {
91    fn chain(&mut self, next: &'d T) -> &mut Self;
92}
93
94pub trait StructureChainQuery {
95    /// Iterate pNext chain
96    fn iter_chain<'a>(&'a self) -> StructureChainIterator<'a>;
97
98    fn query_structure_type(&self, ty: brvk::VkStructureType) -> Option<&brvk::GenericVulkanStructure> {
99        self.iter_chain().find(|s| s.sType == ty)
100    }
101    fn query_structure<S: brvk::TypedVulkanStructure>(&self) -> Option<&S> {
102        self.query_structure_type(S::TYPE)
103            .map(|r| unsafe { r.cast_unchecked() })
104    }
105}
106impl<S: brvk::TypedVulkanStructure> StructureChainQuery for S {
107    #[inline(always)]
108    fn iter_chain<'a>(&'a self) -> StructureChainIterator<'a> {
109        StructureChainIterator {
110            current: self.as_generic() as _,
111            marker: std::marker::PhantomData,
112        }
113    }
114}
115
116pub trait SinkStructureChainQuery {
117    /// Iterate pNext chain
118    fn iter_chain<'a>(&'a self) -> SinkStructureChainIterator<'a>;
119
120    #[inline(always)]
121    fn query_structure_type(&self, ty: brvk::VkStructureType) -> Option<&brvk::GenericVulkanSinkStructure> {
122        self.iter_chain().find(|s| s.sType == ty)
123    }
124
125    #[inline(always)]
126    fn query_structure<S: brvk::TypedVulkanSinkStructure>(&self) -> Option<&S> {
127        self.query_structure_type(S::TYPE)
128            .map(|r| unsafe { r.cast_ref_unchecked() })
129    }
130}
131impl<S: brvk::TypedVulkanSinkStructure> SinkStructureChainQuery for S {
132    #[inline(always)]
133    fn iter_chain<'a>(&'a self) -> SinkStructureChainIterator<'a> {
134        SinkStructureChainIterator {
135            current: self.as_generic() as _,
136            marker: core::marker::PhantomData,
137        }
138    }
139}
140
141/// chains a list of vulkan structures
142pub fn chain_structures<'x>(mut xs: impl Iterator<Item = &'x mut brvk::GenericVulkanStructure>) {
143    let Some(mut p) = xs.next() else {
144        // nothing to be chained
145        return;
146    };
147
148    for q in xs {
149        p.pNext = core::ptr::from_mut(q).cast();
150        p = q;
151    }
152}