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

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