demo_vk/graphics/vulkan/context/
mod.rs

1mod instance;
2mod logical_device;
3mod physical_device;
4
5use {
6    crate::{
7        graphics::vulkan::{raii, Allocator},
8        unwrap_here,
9    },
10    anyhow::Result,
11    ash::vk::{self},
12    std::sync::Arc,
13    winit::window::Window,
14};
15
16pub use self::instance::Instance;
17
18/// Holds all of the device features structs which can be used when creating a
19/// VulkanContext.
20///
21/// Note: None of the pnext pointers should be specified in these structures.
22///       The relevant pnext chain will be assembled on-demand when calling
23///       into Vulkan and never before.
24#[derive(Debug, Default)]
25pub struct RequiredDeviceFeatures {
26    pub physical_device_features: vk::PhysicalDeviceFeatures,
27    pub physical_device_maintenance4_features:
28        vk::PhysicalDeviceMaintenance4Features<'static>,
29    pub physical_device_vulkan12_features:
30        vk::PhysicalDeviceVulkan12Features<'static>,
31    pub physical_device_dynamic_rendering_features:
32        vk::PhysicalDeviceDynamicRenderingFeatures<'static>,
33}
34
35/// The Vulkan context is the logical handle for all Vulkan operations within
36/// the app.
37///
38/// It supports finding and using a single logical device along with all
39/// required queues and a device memory allocator.
40pub struct VulkanContext {
41    pub instance: Instance,
42    pub surface_khr: Arc<raii::Surface>,
43    pub physical_device: vk::PhysicalDevice,
44    pub device: Arc<raii::Device>,
45
46    /// The queue family index for the graphics + present queue.
47    pub graphics_queue_family_index: u32,
48
49    /// The graphics queue supports GRAPHICS and presentation operations.
50    pub graphics_queue: vk::Queue,
51
52    /// The device memory allocator.
53    pub allocator: Arc<Allocator>,
54}
55
56impl VulkanContext {
57    /// Creates a new Vulkan Context for the first suitable device that supports
58    /// presenting to the GLFW window surface.
59    pub fn new(
60        window: &Window,
61        required_device_features: RequiredDeviceFeatures,
62    ) -> Result<Arc<Self>> {
63        let instance = unwrap_here!(
64            "Create Vulkan instance for the application window",
65            Instance::for_window("demo-vk", window)
66        );
67
68        let surface_khr = unwrap_here!(
69            "Create Vulkan surface for the application window",
70            raii::Surface::for_window(instance.ash.clone(), window)
71        );
72
73        let physical_device = unwrap_here!(
74            "Pick a suitable device for the application",
75            physical_device::pick_suitable_device(
76                &instance,
77                &surface_khr,
78                &required_device_features,
79            )
80        );
81
82        let (device, graphics_queue_family_index) = unwrap_here!(
83            "Create a logical device for the chosen physical device",
84            logical_device::create_logical_device(
85                &instance,
86                &surface_khr,
87                physical_device,
88                required_device_features,
89            )
90        );
91
92        let graphics_queue =
93            unsafe { device.get_device_queue(graphics_queue_family_index, 0) };
94
95        let allocator = unwrap_here!(
96            "Create the Vulkan GPU memory allocator",
97            Allocator::new(device.clone(), physical_device)
98        );
99
100        Ok(Arc::new(Self {
101            instance,
102            surface_khr,
103            physical_device,
104            device,
105            graphics_queue_family_index,
106            graphics_queue,
107            allocator: Arc::new(allocator),
108        }))
109    }
110}
111
112impl std::ops::Deref for VulkanContext {
113    type Target = ash::Device;
114
115    fn deref(&self) -> &Self::Target {
116        &self.device.raw
117    }
118}
119
120impl std::fmt::Debug for VulkanContext {
121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122        f.debug_struct("VulkanContext")
123            .field("instance", &self.instance)
124            .field("surface_khr", &self.surface_khr)
125            .field("physical_device", &self.physical_device)
126            .field("device", &self.device)
127            .field(
128                "graphics_queue_family_index",
129                &self.graphics_queue_family_index,
130            )
131            .field("graphics_queue", &self.graphics_queue)
132            .finish()
133    }
134}