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