demo_vk/graphics/vulkan/raii/
device.rs

1use {
2    crate::{graphics::vulkan::raii, trace},
3    anyhow::{Context, Result},
4    ash::{
5        ext::debug_utils,
6        vk::{self, Handle},
7    },
8    std::{ffi::CString, sync::Arc},
9};
10
11/// A RAII wrapper for the Vulkan Logical Device.
12pub struct Device {
13    debug_utils: Option<Arc<ash::ext::debug_utils::Device>>,
14    pub raw: ash::Device,
15    pub ash: Arc<raii::Instance>,
16}
17
18impl Device {
19    pub fn new(
20        instance: Arc<raii::Instance>,
21        physical_device: vk::PhysicalDevice,
22        create_info: &vk::DeviceCreateInfo,
23    ) -> Result<Arc<Self>> {
24        let raw = unsafe {
25            instance
26                .raw
27                .create_device(physical_device, create_info, None)?
28        };
29
30        let debug_utils = Self::create_debug_utils(&instance.raw, &raw);
31        if let Some(debug_utils) = debug_utils.as_ref() {
32            let name = CString::new("My Device").unwrap();
33            unsafe {
34                debug_utils.set_debug_utils_object_name(
35                    &vk::DebugUtilsObjectNameInfoEXT {
36                        object_type: vk::ObjectType::DEVICE,
37                        object_handle: raw.handle().as_raw(),
38                        p_object_name: name.as_ptr(),
39                        ..Default::default()
40                    },
41                )?;
42            }
43        }
44        Ok(Arc::new(Self {
45            debug_utils,
46            raw,
47            ash: instance,
48        }))
49    }
50
51    #[cfg(not(debug_assertions))]
52    pub fn set_debug_name(
53        &self,
54        name_info: &vk::DebugUtilsObjectNameInfoEXT,
55    ) -> Result<()> {
56        Ok(())
57    }
58
59    #[cfg(debug_assertions)]
60    pub fn set_debug_name(
61        &self,
62        name_info: &vk::DebugUtilsObjectNameInfoEXT,
63    ) -> Result<()> {
64        unsafe {
65            self.debug_utils
66                .as_ref()
67                .unwrap()
68                .set_debug_utils_object_name(name_info)
69                .with_context(trace!("Unable to set object debug name"))?
70        }
71        Ok(())
72    }
73
74    #[cfg(not(debug_assertions))]
75    fn create_debug_utils(
76        instance: &ash::Instance,
77        device: &ash::Device,
78    ) -> Option<Arc<debug_utils::Device>> {
79        None
80    }
81
82    #[cfg(debug_assertions)]
83    fn create_debug_utils(
84        instance: &ash::Instance,
85        device: &ash::Device,
86    ) -> Option<Arc<debug_utils::Device>> {
87        Some(Arc::new(ash::ext::debug_utils::Device::new(
88            instance, device,
89        )))
90    }
91}
92
93impl Drop for Device {
94    fn drop(&mut self) {
95        unsafe { self.raw.destroy_device(None) }
96    }
97}
98
99impl std::fmt::Debug for Device {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        f.debug_struct("Device")
102            .field("raw", &"<raw vulkan device handle>")
103            .field("ash", &self.ash)
104            .finish()
105    }
106}
107
108impl std::ops::Deref for Device {
109    type Target = ash::Device;
110
111    fn deref(&self) -> &Self::Target {
112        &self.raw
113    }
114}