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 {
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<Box<dyn ExtendsDeviceProperties2Debug>>,
) -> Result<PhysicalDevice> {
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::<Vec<_>>(),
);
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,

View file

@ -0,0 +1 @@

View file

@ -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<ash::Instance> for Instance {
fn as_ref(&self) -> &ash::Instance {
&self.instance
}
pub struct DebugUtilsCreateInfo {
pub severity: vk::DebugUtilsMessageSeverityFlagsEXT,
pub message_type: vk::DebugUtilsMessageTypeFlagsEXT,
}
impl AsRef<ash::khr::surface::Instance> 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 {

View file

@ -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<Instance>) -> Result<Self> {
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<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.
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<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! {
@ -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<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(
device: Device,
surface: Arc<Surface>,
@ -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());