demo_vk/graphics/vulkan/raii/
instance_extensions.rs

1//! RAII wrappers for Vulkan objects that extend the Vulkan instance.
2
3use {
4    crate::{graphics::vulkan::raii, trace},
5    anyhow::{bail, Result},
6    ash::vk::{self, Handle},
7    std::sync::Arc,
8};
9
10macro_rules! instance_extension {
11    (
12        $name: ident,
13        $ext_type: ty,
14        $raw_type: ty,
15        $destroy: ident
16    ) => {
17        /// RAII wrapper that destroys itself when Dropped.
18        ///
19        /// The owner is responsible for dropping Vulkan resources in the
20        /// correct order.
21        pub struct $name {
22            pub ext: $ext_type,
23            pub raw: $raw_type,
24            pub ash: Arc<raii::Instance>,
25        }
26
27        impl std::fmt::Debug for $name {
28            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29                f.debug_struct(stringify!($name))
30                    .field("ext", &"<extension loader>")
31                    .field("raw", &self.raw)
32                    .field("ash", &self.ash)
33                    .finish()
34            }
35        }
36
37        impl std::ops::Deref for $name {
38            type Target = $raw_type;
39
40            fn deref(&self) -> &Self::Target {
41                &self.raw
42            }
43        }
44
45        impl Drop for $name {
46            fn drop(&mut self) {
47                unsafe { self.ext.$destroy(self.raw, None) }
48            }
49        }
50    };
51}
52
53instance_extension!(
54    DebugUtils,
55    ash::ext::debug_utils::Instance,
56    vk::DebugUtilsMessengerEXT,
57    destroy_debug_utils_messenger
58);
59
60impl DebugUtils {
61    pub fn new(
62        ash: Arc<raii::Instance>,
63        create_info: &vk::DebugUtilsMessengerCreateInfoEXT,
64    ) -> Result<Arc<Self>> {
65        let ext = ash::ext::debug_utils::Instance::new(&ash.entry, &ash);
66        let raw =
67            unsafe { ext.create_debug_utils_messenger(create_info, None)? };
68        Ok(Arc::new(Self { ext, raw, ash }))
69    }
70}
71
72instance_extension!(
73    Surface,
74    ash::khr::surface::Instance,
75    vk::SurfaceKHR,
76    destroy_surface
77);
78
79impl Surface {
80    pub fn new(
81        ash: Arc<raii::Instance>,
82        raw: vk::SurfaceKHR,
83    ) -> Result<Arc<Self>> {
84        let ext = ash::khr::surface::Instance::new(&ash.entry, &ash);
85        Ok(Arc::new(Self { raw, ext, ash }))
86    }
87
88    pub fn for_window(
89        ash: Arc<raii::Instance>,
90        window: &glfw::Window,
91    ) -> Result<Arc<Self>> {
92        let handle = unsafe {
93            let mut surface: std::mem::MaybeUninit<vk::SurfaceKHR> =
94                std::mem::MaybeUninit::uninit();
95            let result = window.create_window_surface(
96                ash.raw.handle().as_raw() as _,
97                std::ptr::null(),
98                surface.as_mut_ptr() as _,
99            );
100            if result != vk::Result::SUCCESS.as_raw() {
101                bail!(trace!("Unable to create Vulkan window surface!")());
102            }
103            surface.assume_init()
104        };
105        Self::new(ash, handle)
106    }
107}