instance refactor

This commit is contained in:
janis 2026-03-26 13:04:27 +01:00
parent c1c69d5e54
commit 41e4a2ed9c
4 changed files with 111 additions and 122 deletions

View file

@ -238,7 +238,7 @@ impl DeviceBuilder {
match display_handle { match display_handle {
RawDisplayHandle::Xlib(display) => { RawDisplayHandle::Xlib(display) => {
let surface = 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( surface.get_physical_device_xlib_presentation_support(
pdev, pdev,
queue_family, queue_family,
@ -249,10 +249,8 @@ impl DeviceBuilder {
} }
RawDisplayHandle::Xcb(_xcb_display_handle) => todo!("xcb"), RawDisplayHandle::Xcb(_xcb_display_handle) => todo!("xcb"),
RawDisplayHandle::Wayland(wayland_display_handle) => { RawDisplayHandle::Wayland(wayland_display_handle) => {
let surface = ash::khr::wayland_surface::Instance::new( let surface =
&instance.entry, ash::khr::wayland_surface::Instance::new(&instance.entry, &instance.raw);
&instance.instance,
);
surface.get_physical_device_wayland_presentation_support( surface.get_physical_device_wayland_presentation_support(
pdev, pdev,
queue_family, queue_family,
@ -263,7 +261,7 @@ impl DeviceBuilder {
todo!() todo!()
} }
RawDisplayHandle::Windows(_) => { 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) .get_physical_device_win32_presentation_support(pdev, queue_family)
} }
_ => panic!("unsupported platform"), _ => panic!("unsupported platform"),
@ -278,7 +276,7 @@ impl DeviceBuilder {
) -> DeviceQueueFamilies { ) -> DeviceQueueFamilies {
let queue_familiy_properties = unsafe { let queue_familiy_properties = unsafe {
instance instance
.instance .raw
.get_physical_device_queue_family_properties(pdev) .get_physical_device_queue_family_properties(pdev)
}; };
@ -461,7 +459,7 @@ impl DeviceBuilder {
requirements: &PhysicalDeviceFeatures, requirements: &PhysicalDeviceFeatures,
extra_properties: Vec<Box<dyn ExtendsDeviceProperties2Debug>>, extra_properties: Vec<Box<dyn ExtendsDeviceProperties2Debug>>,
) -> Result<PhysicalDevice> { ) -> Result<PhysicalDevice> {
let pdevs = unsafe { instance.instance.enumerate_physical_devices()? }; let pdevs = unsafe { instance.raw.enumerate_physical_devices()? };
let (pdev, properties) = pdevs let (pdev, properties) = pdevs
.into_iter() .into_iter()
@ -472,7 +470,7 @@ impl DeviceBuilder {
.map(|b| dyn_clone::clone_box(&**b)) .map(|b| dyn_clone::clone_box(&**b))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
); );
props.query(&instance.instance, pdev); props.query(&instance.raw, pdev);
(pdev, props) (pdev, props)
}) })
@ -483,8 +481,7 @@ impl DeviceBuilder {
// TODO: figure out a way to fall back to some // TODO: figure out a way to fall back to some
// device which doesn't support all of the extensions. // device which doesn't support all of the extensions.
.filter(|(pdev, _)| { .filter(|(pdev, _)| {
let query_features = let query_features = PhysicalDeviceFeatures::query(&instance.raw, *pdev).unwrap();
PhysicalDeviceFeatures::query(&instance.instance, *pdev).unwrap();
requirements.compatible_with(&query_features) requirements.compatible_with(&query_features)
}) })
@ -794,30 +791,32 @@ impl Device {
let instance = unsafe { entry.create_instance(&create_info, None)? }; let instance = unsafe { entry.create_instance(&create_info, None)? };
let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::default() let debug_utils = {
.message_severity( let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::default()
vk::DebugUtilsMessageSeverityFlagsEXT::ERROR .message_severity(
| vk::DebugUtilsMessageSeverityFlagsEXT::WARNING vk::DebugUtilsMessageSeverityFlagsEXT::ERROR
| vk::DebugUtilsMessageSeverityFlagsEXT::INFO, | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING
) | vk::DebugUtilsMessageSeverityFlagsEXT::INFO,
.message_type( )
vk::DebugUtilsMessageTypeFlagsEXT::GENERAL .message_type(
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE, | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
) | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE,
.pfn_user_callback(Some(crate::debug::debug_callback)); )
.pfn_user_callback(Some(crate::debug::debug_callback));
let debug_utils_instance = ash::ext::debug_utils::Instance::new(&entry, &instance); let instance = ext::debug_utils::Instance::new(&entry, &instance);
let debug_utils_messenger = let messenger = unsafe { instance.create_debug_utils_messenger(&debug_info, None)? };
unsafe { debug_utils_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 { let instance = Arc::new(Instance {
instance, raw: instance,
debug_utils: debug_utils_instance, _debug_utils: debug_utils,
debug_utils_messenger,
surface: surface_instance,
entry, entry,
}); });
@ -885,7 +884,7 @@ impl Device {
tracing::debug!("creating device: {:#?}", device_info); tracing::debug!("creating device: {:#?}", device_info);
let device = unsafe { let device = unsafe {
let device = instance let device = instance
.instance .raw
.create_device(physical.pdev, &device_info, None)?; .create_device(physical.pdev, &device_info, None)?;
tracing::debug!("allocating queues: {queue_infos:#?}"); tracing::debug!("allocating queues: {queue_infos:#?}");
@ -919,15 +918,15 @@ impl Device {
let transfer_queue = get_queue(physical.queue_families.transfer); let transfer_queue = get_queue(physical.queue_families.transfer);
let alloc_info = 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)?; let alloc = vk_mem::Allocator::new(alloc_info)?;
DeviceInner { DeviceInner {
device: DeviceWrapper(device.clone()), device: DeviceWrapper(device.clone()),
physical, physical,
swapchain: khr::swapchain::Device::new(&instance.instance, &device), swapchain: khr::swapchain::Device::new(&instance.raw, &device),
debug_utils: ash::ext::debug_utils::Device::new(&instance.instance, &device), debug_utils: ash::ext::debug_utils::Device::new(&instance.raw, &device),
instance, instance,
alloc, alloc,
allocated_queues, allocated_queues,

View file

@ -0,0 +1 @@

View file

@ -13,7 +13,7 @@ use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use parking_lot::{Mutex, MutexGuard}; use parking_lot::{Mutex, MutexGuard};
use ash::{ use ash::{
Entry, Entry, ext,
prelude::VkResult, prelude::VkResult,
vk::{self}, vk::{self},
}; };
@ -28,6 +28,7 @@ pub mod device;
#[path = "egui.rs"] #[path = "egui.rs"]
mod egui_pass; mod egui_pass;
mod images; mod images;
pub mod instance;
mod memory; mod memory;
mod pipeline; mod pipeline;
pub mod render_graph; pub mod render_graph;
@ -434,32 +435,29 @@ pub struct PhysicalDevice {
properties: PhysicalDeviceProperties, properties: PhysicalDeviceProperties,
} }
pub struct Instance { struct DebugUtils {
entry: Entry, instance: ext::debug_utils::Instance,
instance: ash::Instance, messenger: vk::DebugUtilsMessengerEXT,
debug_utils: ash::ext::debug_utils::Instance,
debug_utils_messenger: vk::DebugUtilsMessengerEXT,
surface: ash::khr::surface::Instance,
} }
impl Drop for Instance { impl Drop for DebugUtils {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
self.debug_utils self.instance
.destroy_debug_utils_messenger(self.debug_utils_messenger, None); .destroy_debug_utils_messenger(self.messenger, None);
} }
} }
} }
impl AsRef<ash::Instance> for Instance { pub struct DebugUtilsCreateInfo {
fn as_ref(&self) -> &ash::Instance { pub severity: vk::DebugUtilsMessageSeverityFlagsEXT,
&self.instance pub message_type: vk::DebugUtilsMessageTypeFlagsEXT,
}
} }
impl AsRef<ash::khr::surface::Instance> for Instance {
fn as_ref(&self) -> &ash::khr::surface::Instance { pub struct Instance {
&self.surface entry: Entry,
} raw: ash::Instance,
_debug_utils: DebugUtils,
} }
pub struct SamplerCache { pub struct SamplerCache {

View file

@ -22,6 +22,7 @@ use crate::{
}; };
use derive_more::Debug; use derive_more::Debug;
#[derive(Debug)] #[derive(Debug)]
pub struct Surface { pub struct Surface {
raw: vk::SurfaceKHR, raw: vk::SurfaceKHR,
@ -41,8 +42,8 @@ impl Surface {
#[allow(dead_code)] #[allow(dead_code)]
pub fn headless(instance: &Arc<Instance>) -> Result<Self> { pub fn headless(instance: &Arc<Instance>) -> Result<Self> {
let headless_instance = let headless_instance =
ash::ext::headless_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.instance); 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. // 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 // (note): ash marks this function as unsafe, likely because of
@ -70,12 +71,12 @@ impl Surface {
display_handle: RawDisplayHandle, display_handle: RawDisplayHandle,
window_handle: RawWindowHandle, window_handle: RawWindowHandle,
) -> Result<Self> { ) -> Result<Self> {
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. // 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 { let surface = unsafe {
ash_window::create_surface( ash_window::create_surface(
&instance.entry, &instance.entry,
&instance.instance, &instance.raw,
display_handle, display_handle,
window_handle, window_handle,
None, None,
@ -87,6 +88,60 @@ impl Surface {
functor, functor,
}) })
} }
fn get_swapchain_params(
&self,
pdev: vk::PhysicalDevice,
requested_extent: Option<vk::Extent2D>,
) -> Result<SwapchainParams> {
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! { define_device_owned_handle! {
@ -162,70 +217,6 @@ impl core::fmt::Debug for Swapchain {
impl Swapchain { impl Swapchain {
const PREFERRED_IMAGES_IN_FLIGHT: u32 = 3; const PREFERRED_IMAGES_IN_FLIGHT: u32 = 3;
fn get_swapchain_params_from_surface(
instance: &Arc<Instance>,
surface: vk::SurfaceKHR,
pdev: vk::PhysicalDevice,
requested_extent: Option<vk::Extent2D>,
) -> Result<SwapchainParams> {
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( pub fn new(
device: Device, device: Device,
surface: Arc<Surface>, surface: Arc<Surface>,
@ -249,7 +240,7 @@ impl Swapchain {
image_count, image_count,
min_image_count, min_image_count,
extent, extent,
} = Self::get_swapchain_params_from_surface(device.instance(), surface.raw, pdev, extent)?; } = surface.get_swapchain_params(pdev, extent)?;
let (swapchain, images) = { let (swapchain, images) = {
let lock = old_swapchain.as_ref().map(|handle| handle.lock()); let lock = old_swapchain.as_ref().map(|handle| handle.lock());