demo_vk/graphics/vulkan/context/instance/
mod.rs

1mod debug;
2
3use {
4    crate::{graphics::vulkan::raii, unwrap_here},
5    anyhow::{Context, Result},
6    ash::vk,
7    std::{ffi::CStr, sync::Arc},
8    winit::{raw_window_handle::HasDisplayHandle, window::Window},
9};
10
11const VK_EXT_DEBUG_UTILS: &CStr = c"VK_EXT_debug_utils";
12
13/// The logical Vulkan instance.
14///
15/// The instance contains the ash library entry, instance, and any associated
16/// debugging information. Within the scope of this library, the Instance is
17/// expected to outlive all other Vulkan resources e.g. it should only be
18/// dropped once all other resources have been destroyed or dropped.
19pub struct Instance {
20    pub ash: Arc<raii::Instance>,
21    extensions: Vec<String>,
22    _debug_utils: Option<Arc<raii::DebugUtils>>,
23}
24
25impl Instance {
26    /// Create a new Vulkan instance for the given GLFW window.
27    pub fn for_window(
28        app_name: impl AsRef<str>,
29        window: &Window,
30    ) -> Result<Self> {
31        let extensions = ash_window::enumerate_required_extensions(
32            window
33                .display_handle()
34                .with_context(|| "Unable to fetch display handle!")?
35                .as_raw(),
36        )?;
37        Self::new(app_name, extensions)
38    }
39
40    /// Create a new Vulkan instance.
41    pub fn new(
42        app_name: impl AsRef<str>,
43        extensions: &[*const i8],
44    ) -> Result<Self> {
45        let ptrs = {
46            let mut ptrs = extensions.to_vec();
47            if cfg!(debug_assertions) {
48                ptrs.push(VK_EXT_DEBUG_UTILS.as_ptr());
49            }
50            ptrs
51        };
52
53        let app_name_c = std::ffi::CString::new(app_name.as_ref()).unwrap();
54        let engine_name = std::ffi::CString::new("N/A").unwrap();
55        let application_info = vk::ApplicationInfo {
56            p_application_name: app_name_c.as_ptr(),
57            application_version: vk::make_api_version(0, 1, 0, 0),
58            p_engine_name: engine_name.as_ptr(),
59            engine_version: vk::make_api_version(0, 1, 0, 0),
60            api_version: vk::make_api_version(0, 1, 3, 0),
61            ..Default::default()
62        };
63        let create_info = vk::InstanceCreateInfo {
64            p_application_info: &application_info,
65            enabled_extension_count: ptrs.len() as u32,
66            pp_enabled_extension_names: ptrs.as_ptr(),
67            ..Default::default()
68        };
69
70        let ash = unwrap_here!(
71            "Create Vulkan instance",
72            raii::Instance::new(&create_info)
73        );
74
75        let debug_utils = unwrap_here!(
76            "Setup debug logging.",
77            debug::setup_debug_logging(ash.clone())
78        );
79
80        Ok(Self {
81            ash,
82            extensions:
83        ptrs.iter().map(|&ptr| {
84            unsafe { CStr::from_ptr(ptr) }.to_string_lossy().to_string()
85        }).collect(),
86            _debug_utils: debug_utils,
87        })
88    }
89}
90
91impl std::fmt::Debug for Instance {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        f.debug_struct("Instance")
94            .field("extensions", &self.extensions)
95            .field("ash", &self.ash)
96            .finish()
97    }
98}
99
100impl std::ops::Deref for Instance {
101    type Target = ash::Instance;
102
103    fn deref(&self) -> &Self::Target {
104        &self.ash.raw
105    }
106}