Skip to main content

ursus_core/vulkan/
mod.rs

1pub mod core;
2pub mod gfx_pipeline;
3pub mod renderer;
4pub mod resources;
5pub mod timestamps;
6
7pub use core::debug::DebugMessenger;
8pub use core::device::Device;
9pub use core::instance::Instance;
10pub use core::swapchain::Swapchain;
11pub use gfx_pipeline::Pipeline;
12pub use renderer::{build_dyn_renderer, DynRenderer, Renderer};
13pub use resources::bindless::BindlessSet;
14pub use resources::mapped_buffer::MappedGpuBuffer;
15pub use resources::texture::GpuTexture;
16
17use crate::EngineFlags;
18use ash::ext::debug_utils;
19use ash::vk;
20use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
21use std::sync::Arc;
22
23pub struct VulkanContext {
24    pub swapchain: Option<Swapchain>,
25    pub device: Arc<Device>,
26    pub surface: vk::SurfaceKHR,
27    _debug: Option<DebugMessenger>,
28    pub debug_utils: Option<Arc<debug_utils::Device>>,
29    pub instance: Arc<Instance>,
30}
31
32impl VulkanContext {
33    pub fn from_handles(
34        display: RawDisplayHandle,
35        window: RawWindowHandle,
36        flags: EngineFlags,
37    ) -> anyhow::Result<Self> {
38        let instance = Arc::new(Instance::new(display, flags.validation, flags.debug_labels)?);
39
40        let validation_active = instance.validation_active;
41        let debug_utils_active = instance.debug_utils_active;
42
43        let debug = if validation_active {
44            Some(DebugMessenger::new(&instance)?)
45        } else {
46            None
47        };
48
49        let surface = unsafe { ash_window::create_surface(&instance.entry, &instance.handle, display, window, None)? };
50
51        let device = Arc::new(Device::new(&instance, surface)?);
52
53        let swapchain = Swapchain::new(&instance, &device, surface, 1280, 720, false)?;
54
55        let debug_utils = if debug_utils_active {
56            Some(Arc::new(debug_utils::Device::new(&instance.handle, &device.handle)))
57        } else {
58            None
59        };
60
61        Ok(Self { swapchain: Some(swapchain), debug_utils, device, surface, _debug: debug, instance })
62    }
63
64    pub fn new(window: &winit::window::Window, flags: EngineFlags) -> anyhow::Result<Self> {
65        use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
66        let display = window.display_handle()?.as_raw();
67        let whandle = window.window_handle()?.as_raw();
68        let size = window.inner_size();
69
70        let mut ctx = Self::from_handles(display, whandle, flags)?;
71        ctx.recreate_swapchain(size.width, size.height, false)?;
72        Ok(ctx)
73    }
74
75    pub fn recreate_swapchain(&mut self, width: u32, height: u32, vsync: bool) -> anyhow::Result<()> {
76        unsafe { self.device.handle.device_wait_idle()? };
77        drop(self.swapchain.take());
78        self.swapchain = Some(Swapchain::new(&self.instance, &self.device, self.surface, width, height, vsync)?);
79        Ok(())
80    }
81}
82
83impl Drop for VulkanContext {
84    fn drop(&mut self) {
85        unsafe {
86            self.device.handle.device_wait_idle().ok();
87            drop(self.swapchain.take());
88            let surface_loader = ash::khr::surface::Instance::new(&self.instance.entry, &self.instance.handle);
89            surface_loader.destroy_surface(self.surface, None);
90        }
91    }
92}