diff --git a/crates/renderer/src/device.rs b/crates/renderer/src/device.rs index eb20299..e84bbdd 100644 --- a/crates/renderer/src/device.rs +++ b/crates/renderer/src/device.rs @@ -238,7 +238,7 @@ impl DeviceBuilder { match display_handle { RawDisplayHandle::Xlib(display) => { let surface = - ash::khr::xlib_surface::Instance::new(&instance.entry, &instance.instance); + ash::khr::xlib_surface::Instance::new(&instance.entry, &instance.raw); surface.get_physical_device_xlib_presentation_support( pdev, queue_family, @@ -249,10 +249,8 @@ impl DeviceBuilder { } RawDisplayHandle::Xcb(_xcb_display_handle) => todo!("xcb"), RawDisplayHandle::Wayland(wayland_display_handle) => { - let surface = ash::khr::wayland_surface::Instance::new( - &instance.entry, - &instance.instance, - ); + let surface = + ash::khr::wayland_surface::Instance::new(&instance.entry, &instance.raw); surface.get_physical_device_wayland_presentation_support( pdev, queue_family, @@ -263,7 +261,7 @@ impl DeviceBuilder { todo!() } RawDisplayHandle::Windows(_) => { - ash::khr::win32_surface::Instance::new(&instance.entry, &instance.instance) + ash::khr::win32_surface::Instance::new(&instance.entry, &instance.raw) .get_physical_device_win32_presentation_support(pdev, queue_family) } _ => panic!("unsupported platform"), @@ -278,7 +276,7 @@ impl DeviceBuilder { ) -> DeviceQueueFamilies { let queue_familiy_properties = unsafe { instance - .instance + .raw .get_physical_device_queue_family_properties(pdev) }; @@ -461,7 +459,7 @@ impl DeviceBuilder { requirements: &PhysicalDeviceFeatures, extra_properties: Vec>, ) -> Result { - let pdevs = unsafe { instance.instance.enumerate_physical_devices()? }; + let pdevs = unsafe { instance.raw.enumerate_physical_devices()? }; let (pdev, properties) = pdevs .into_iter() @@ -472,7 +470,7 @@ impl DeviceBuilder { .map(|b| dyn_clone::clone_box(&**b)) .collect::>(), ); - props.query(&instance.instance, pdev); + props.query(&instance.raw, pdev); (pdev, props) }) @@ -483,8 +481,7 @@ impl DeviceBuilder { // TODO: figure out a way to fall back to some // device which doesn't support all of the extensions. .filter(|(pdev, _)| { - let query_features = - PhysicalDeviceFeatures::query(&instance.instance, *pdev).unwrap(); + let query_features = PhysicalDeviceFeatures::query(&instance.raw, *pdev).unwrap(); requirements.compatible_with(&query_features) }) @@ -794,30 +791,32 @@ impl Device { let instance = unsafe { entry.create_instance(&create_info, None)? }; - let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::default() - .message_severity( - vk::DebugUtilsMessageSeverityFlagsEXT::ERROR - | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING - | vk::DebugUtilsMessageSeverityFlagsEXT::INFO, - ) - .message_type( - vk::DebugUtilsMessageTypeFlagsEXT::GENERAL - | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION - | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE, - ) - .pfn_user_callback(Some(crate::debug::debug_callback)); + let debug_utils = { + let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::default() + .message_severity( + vk::DebugUtilsMessageSeverityFlagsEXT::ERROR + | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING + | vk::DebugUtilsMessageSeverityFlagsEXT::INFO, + ) + .message_type( + vk::DebugUtilsMessageTypeFlagsEXT::GENERAL + | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION + | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE, + ) + .pfn_user_callback(Some(crate::debug::debug_callback)); - let debug_utils_instance = ash::ext::debug_utils::Instance::new(&entry, &instance); - let debug_utils_messenger = - unsafe { debug_utils_instance.create_debug_utils_messenger(&debug_info, None)? }; + let instance = ext::debug_utils::Instance::new(&entry, &instance); + let messenger = unsafe { instance.create_debug_utils_messenger(&debug_info, None)? }; - let surface_instance = ash::khr::surface::Instance::new(&entry, &instance); + crate::DebugUtils { + instance, + messenger, + } + }; let instance = Arc::new(Instance { - instance, - debug_utils: debug_utils_instance, - debug_utils_messenger, - surface: surface_instance, + raw: instance, + _debug_utils: debug_utils, entry, }); @@ -885,7 +884,7 @@ impl Device { tracing::debug!("creating device: {:#?}", device_info); let device = unsafe { let device = instance - .instance + .raw .create_device(physical.pdev, &device_info, None)?; tracing::debug!("allocating queues: {queue_infos:#?}"); @@ -919,15 +918,15 @@ impl Device { let transfer_queue = get_queue(physical.queue_families.transfer); let alloc_info = - vk_mem::AllocatorCreateInfo::new(&instance.instance, &device, physical.pdev); + vk_mem::AllocatorCreateInfo::new(&instance.raw, &device, physical.pdev); let alloc = vk_mem::Allocator::new(alloc_info)?; DeviceInner { device: DeviceWrapper(device.clone()), physical, - swapchain: khr::swapchain::Device::new(&instance.instance, &device), - debug_utils: ash::ext::debug_utils::Device::new(&instance.instance, &device), + swapchain: khr::swapchain::Device::new(&instance.raw, &device), + debug_utils: ash::ext::debug_utils::Device::new(&instance.raw, &device), instance, alloc, allocated_queues, diff --git a/crates/renderer/src/instance.rs b/crates/renderer/src/instance.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/renderer/src/instance.rs @@ -0,0 +1 @@ + diff --git a/crates/renderer/src/lib.rs b/crates/renderer/src/lib.rs index 39b4c9f..99fb292 100644 --- a/crates/renderer/src/lib.rs +++ b/crates/renderer/src/lib.rs @@ -13,7 +13,7 @@ use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use parking_lot::{Mutex, MutexGuard}; use ash::{ - Entry, + Entry, ext, prelude::VkResult, vk::{self}, }; @@ -28,6 +28,7 @@ pub mod device; #[path = "egui.rs"] mod egui_pass; mod images; +pub mod instance; mod memory; mod pipeline; pub mod render_graph; @@ -434,32 +435,29 @@ pub struct PhysicalDevice { properties: PhysicalDeviceProperties, } -pub struct Instance { - entry: Entry, - instance: ash::Instance, - debug_utils: ash::ext::debug_utils::Instance, - debug_utils_messenger: vk::DebugUtilsMessengerEXT, - surface: ash::khr::surface::Instance, +struct DebugUtils { + instance: ext::debug_utils::Instance, + messenger: vk::DebugUtilsMessengerEXT, } -impl Drop for Instance { +impl Drop for DebugUtils { fn drop(&mut self) { unsafe { - self.debug_utils - .destroy_debug_utils_messenger(self.debug_utils_messenger, None); + self.instance + .destroy_debug_utils_messenger(self.messenger, None); } } } -impl AsRef for Instance { - fn as_ref(&self) -> &ash::Instance { - &self.instance - } +pub struct DebugUtilsCreateInfo { + pub severity: vk::DebugUtilsMessageSeverityFlagsEXT, + pub message_type: vk::DebugUtilsMessageTypeFlagsEXT, } -impl AsRef for Instance { - fn as_ref(&self) -> &ash::khr::surface::Instance { - &self.surface - } + +pub struct Instance { + entry: Entry, + raw: ash::Instance, + _debug_utils: DebugUtils, } pub struct SamplerCache { diff --git a/crates/renderer/src/swapchain.rs b/crates/renderer/src/swapchain.rs index 528c247..f59598b 100644 --- a/crates/renderer/src/swapchain.rs +++ b/crates/renderer/src/swapchain.rs @@ -22,6 +22,7 @@ use crate::{ }; use derive_more::Debug; + #[derive(Debug)] pub struct Surface { raw: vk::SurfaceKHR, @@ -41,8 +42,8 @@ impl Surface { #[allow(dead_code)] pub fn headless(instance: &Arc) -> Result { let headless_instance = - ash::ext::headless_surface::Instance::new(&instance.entry, &instance.instance); - let functor = khr::surface::Instance::new(&instance.entry, &instance.instance); + ash::ext::headless_surface::Instance::new(&instance.entry, &instance.raw); + let functor = khr::surface::Instance::new(&instance.entry, &instance.raw); // SAFETY: the headless surface does not have any platform-specific requirements, and does not depend on any external handles, so it is safe to create without additional guarantees. // (note): ash marks this function as unsafe, likely because of @@ -70,12 +71,12 @@ impl Surface { display_handle: RawDisplayHandle, window_handle: RawWindowHandle, ) -> Result { - let functor = khr::surface::Instance::new(&instance.entry, &instance.instance); + let functor = khr::surface::Instance::new(&instance.entry, &instance.raw); // SAFETY: the caller guarantees the validity of the display and window handles, and that they remain valid for the lifetime of the surface. let surface = unsafe { ash_window::create_surface( &instance.entry, - &instance.instance, + &instance.raw, display_handle, window_handle, None, @@ -87,6 +88,60 @@ impl Surface { functor, }) } + + fn get_swapchain_params( + &self, + pdev: vk::PhysicalDevice, + requested_extent: Option, + ) -> Result { + let functor = &self.functor; + let raw = self.raw; + let caps = unsafe { functor.get_physical_device_surface_capabilities(pdev, raw)? }; + let formats = unsafe { functor.get_physical_device_surface_formats(pdev, raw)? }; + let present_modes = + unsafe { functor.get_physical_device_surface_present_modes(pdev, raw)? }; + + let present_mode = present_modes + .iter() + .find(|&mode| mode == &vk::PresentModeKHR::MAILBOX) + .cloned() + .unwrap_or(vk::PresentModeKHR::FIFO); + + let format = formats + .iter() + .max_by_key(|&&format| { + let is_rgba_unorm = format.format == vk::Format::R8G8B8A8_UNORM + || format.format == vk::Format::B8G8R8A8_UNORM; + let is_srgb = format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR; + is_rgba_unorm as u8 * 10 + is_srgb as u8 + }) + .or(formats.first()) + .cloned() + .expect("no surface format available!"); + + // 0 here means no limit + let max_image_count = core::num::NonZero::new(caps.max_image_count) + .map(|n| n.get()) + .unwrap_or(u32::MAX); + + // we want PREFERRED_IMAGES_IN_FLIGHT images acquired at the same time, + let image_count = + (caps.min_image_count + Swapchain::PREFERRED_IMAGES_IN_FLIGHT).min(max_image_count); + + let extent = current_extent_or_clamped( + &caps, + requested_extent.unwrap_or(vk::Extent2D::default().width(1).height(1)), + ); + + Ok(SwapchainParams { + present_mode, + format: format.format, + color_space: format.color_space, + image_count, + extent, + min_image_count: caps.min_image_count, + }) + } } define_device_owned_handle! { @@ -162,70 +217,6 @@ impl core::fmt::Debug for Swapchain { impl Swapchain { const PREFERRED_IMAGES_IN_FLIGHT: u32 = 3; - fn get_swapchain_params_from_surface( - instance: &Arc, - surface: vk::SurfaceKHR, - pdev: vk::PhysicalDevice, - requested_extent: Option, - ) -> Result { - let caps = unsafe { - instance - .surface - .get_physical_device_surface_capabilities(pdev, surface)? - }; - let formats = unsafe { - instance - .surface - .get_physical_device_surface_formats(pdev, surface)? - }; - let present_modes = unsafe { - instance - .surface - .get_physical_device_surface_present_modes(pdev, surface)? - }; - - let present_mode = present_modes - .iter() - .find(|&mode| mode == &vk::PresentModeKHR::MAILBOX) - .cloned() - .unwrap_or(vk::PresentModeKHR::FIFO); - - let format = formats - .iter() - .max_by_key(|&&format| { - let is_rgba_unorm = format.format == vk::Format::R8G8B8A8_UNORM - || format.format == vk::Format::B8G8R8A8_UNORM; - let is_srgb = format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR; - is_rgba_unorm as u8 * 10 + is_srgb as u8 - }) - .or(formats.first()) - .cloned() - .expect("no surface format available!"); - - // 0 here means no limit - let max_image_count = core::num::NonZero::new(caps.max_image_count) - .map(|n| n.get()) - .unwrap_or(u32::MAX); - - // we want PREFERRED_IMAGES_IN_FLIGHT images acquired at the same time, - let image_count = - (caps.min_image_count + Self::PREFERRED_IMAGES_IN_FLIGHT).min(max_image_count); - - let extent = current_extent_or_clamped( - &caps, - requested_extent.unwrap_or(vk::Extent2D::default().width(1).height(1)), - ); - - Ok(SwapchainParams { - present_mode, - format: format.format, - color_space: format.color_space, - image_count, - extent, - min_image_count: caps.min_image_count, - }) - } - pub fn new( device: Device, surface: Arc, @@ -249,7 +240,7 @@ impl Swapchain { image_count, min_image_count, extent, - } = Self::get_swapchain_params_from_surface(device.instance(), surface.raw, pdev, extent)?; + } = surface.get_swapchain_params(pdev, extent)?; let (swapchain, images) = { let lock = old_swapchain.as_ref().map(|handle| handle.lock());