instance refactor

This commit is contained in:
janis 2026-03-26 23:18:02 +01:00
parent 41e4a2ed9c
commit 20f743d74b
4 changed files with 380 additions and 294 deletions

View file

@ -16,7 +16,8 @@ use tinyvec::{ArrayVec, array_vec};
use crate::{ use crate::{
Error, ExtendsDeviceProperties2Debug, Instance, PhysicalDevice, PhysicalDeviceFeatures, Error, ExtendsDeviceProperties2Debug, Instance, PhysicalDevice, PhysicalDeviceFeatures,
PhysicalDeviceProperties, Queue, Result, VkNameList, make_extention_properties, sync, PhysicalDeviceProperties, Queue, Result, VkNameList, instance::InstanceInner,
make_extention_properties, sync,
}; };
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -114,7 +115,7 @@ pub struct DeviceInner {
alloc: vk_mem::Allocator, alloc: vk_mem::Allocator,
device: DeviceWrapper, device: DeviceWrapper,
physical: PhysicalDevice, physical: PhysicalDevice,
instance: Arc<Instance>, instance: Arc<InstanceInner>,
swapchain: khr::swapchain::Device, swapchain: khr::swapchain::Device,
debug_utils: ash::ext::debug_utils::Device, debug_utils: ash::ext::debug_utils::Device,
allocated_queues: BTreeMap<(u32, u32), Queue>, allocated_queues: BTreeMap<(u32, u32), Queue>,
@ -137,18 +138,18 @@ impl core::fmt::Debug for DeviceInner {
} }
#[macro_export] #[macro_export]
macro_rules! make_extention { macro_rules! make_extension {
($module:path) => {{ ($module:path) => {{
use $module::{NAME as EXTENSION_NAME, SPEC_VERSION as EXTENSION_VERSION}; use $module::{NAME as EXTENSION_NAME, SPEC_VERSION as EXTENSION_VERSION};
Extension { $crate::device::Extension {
name: EXTENSION_NAME.to_str().unwrap(), name: EXTENSION_NAME,
version: EXTENSION_VERSION, version: EXTENSION_VERSION,
} }
}}; }};
($module:path as $version:expr) => {{ ($module:path as $version:expr) => {{
use $module::*; use $module::*;
Extension { $crate::device::Extension {
name: NAME.to_str().unwrap(), name: NAME,
version: $version, version: $version,
} }
}}; }};
@ -156,7 +157,7 @@ macro_rules! make_extention {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Extension<'a> { pub struct Extension<'a> {
pub name: &'a str, pub name: &'a CStr,
pub version: u32, pub version: u32,
} }
@ -229,7 +230,7 @@ struct DeviceBuilder;
impl DeviceBuilder { impl DeviceBuilder {
fn queue_family_supports_presentation( fn queue_family_supports_presentation(
instance: &Instance, instance: &Arc<InstanceInner>,
pdev: vk::PhysicalDevice, pdev: vk::PhysicalDevice,
queue_family: u32, queue_family: u32,
display_handle: RawDisplayHandle, display_handle: RawDisplayHandle,
@ -270,7 +271,7 @@ impl DeviceBuilder {
} }
fn select_pdev_queue_families( fn select_pdev_queue_families(
instance: &Instance, instance: &Arc<InstanceInner>,
display_handle: Option<RawDisplayHandle>, display_handle: Option<RawDisplayHandle>,
pdev: vk::PhysicalDevice, pdev: vk::PhysicalDevice,
) -> DeviceQueueFamilies { ) -> DeviceQueueFamilies {
@ -454,7 +455,7 @@ impl DeviceBuilder {
} }
fn choose_physical_device( fn choose_physical_device(
instance: &Instance, instance: &Arc<InstanceInner>,
display_handle: Option<RawDisplayHandle>, display_handle: Option<RawDisplayHandle>,
requirements: &PhysicalDeviceFeatures, requirements: &PhysicalDeviceFeatures,
extra_properties: Vec<Box<dyn ExtendsDeviceProperties2Debug>>, extra_properties: Vec<Box<dyn ExtendsDeviceProperties2Debug>>,
@ -505,8 +506,9 @@ impl DeviceBuilder {
properties, properties,
}) })
} }
}
fn get_available_extensions( pub(crate) fn get_available_extensions(
entry: &ash::Entry, entry: &ash::Entry,
layers: &[&CStr], layers: &[&CStr],
) -> Result<Vec<ash::vk::ExtensionProperties>> { ) -> Result<Vec<ash::vk::ExtensionProperties>> {
@ -526,14 +528,13 @@ impl DeviceBuilder {
} }
/// returns a tuple of supported-or-enabled extensions and unsupported-and-requested extensions /// returns a tuple of supported-or-enabled extensions and unsupported-and-requested extensions
fn get_extensions<'a>( pub(crate) fn get_extensions<'a>(
entry: &ash::Entry, entry: &ash::Entry,
layers: &[&'a CStr], layers: &[&'a CStr],
extensions: impl Iterator<Item = Extension<'a>> + 'a, mut extensions: Vec<Extension<'a>>,
display_handle: Option<RawDisplayHandle>, display_handle: Option<RawDisplayHandle>,
) -> Result<(HashSet<Extension<'a>>, HashSet<Extension<'a>>)> { ) -> Result<(HashSet<Extension<'a>>, HashSet<Extension<'a>>)> {
unsafe { let available_extensions = get_available_extensions(entry, layers)?;
let available_extensions = Self::get_available_extensions(entry, layers)?;
let available_extension_names = available_extensions let available_extension_names = available_extensions
.iter() .iter()
@ -550,102 +551,117 @@ impl DeviceBuilder {
available_extension_names.iter().collect::<Vec<_>>() available_extension_names.iter().collect::<Vec<_>>()
); );
let mut out_extensions = HashSet::new();
let mut unsupported_extensions = HashSet::new();
let mut wsi_extensions = Vec::new(); let mut wsi_extensions = Vec::new();
wsi_extensions.push(make_extention!(khr::surface)); wsi_extensions.push(make_extension!(khr::surface));
// taken from wgpu-hal/src/vulkan/instance.rs: // taken from wgpu-hal/src/vulkan/instance.rs:
//
// we want to enable all the wsi extensions that are applicable to the
// platform, even if the user didn't explicitly request them, or
// supplied a different/no display handle, because we might later want
// to create a surface for a different windowing system, and enabling
// all the wsi extensions doesn't have any real downsides.
// We don't notify the user if some of these extensions aren't available
// (e.g. because wayland isn't supported on some unix system)
if cfg!(all( if cfg!(all(
unix, unix,
not(target_os = "android"), not(target_os = "android"),
not(target_os = "macos") not(target_os = "macos")
)) { )) {
wsi_extensions.push(make_extention!(khr::xlib_surface)); wsi_extensions.push(make_extension!(khr::xlib_surface));
wsi_extensions.push(make_extention!(khr::xcb_surface)); wsi_extensions.push(make_extension!(khr::xcb_surface));
wsi_extensions.push(make_extention!(khr::wayland_surface)); wsi_extensions.push(make_extension!(khr::wayland_surface));
} }
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
wsi_extensions.push(make_extention!(khr::win32_surface)); wsi_extensions.push(make_extension!(khr::win32_surface));
} }
if cfg!(target_os = "android") { if cfg!(target_os = "android") {
wsi_extensions.push(make_extention!(khr::android_surface)); wsi_extensions.push(make_extension!(khr::android_surface));
} }
if cfg!(target_os = "macos") { if cfg!(target_os = "macos") {
wsi_extensions.push(make_extention!(ext::metal_surface)); wsi_extensions.push(make_extension!(ext::metal_surface));
wsi_extensions.push(make_extention!(khr::portability_enumeration)); wsi_extensions.push(make_extension!(khr::portability_enumeration));
} }
if cfg!(all( if cfg!(all(
unix, unix,
not(target_vendor = "apple"), not(target_vendor = "apple"),
not(target_family = "wasm") not(target_family = "wasm")
)) { )) {
wsi_extensions.push(make_extention!(ext::acquire_drm_display)); wsi_extensions.push(make_extension!(ext::acquire_drm_display));
wsi_extensions.push(make_extention!(ext::direct_mode_display)); wsi_extensions.push(make_extension!(ext::direct_mode_display));
wsi_extensions.push(make_extention!(khr::display)); wsi_extensions.push(make_extension!(khr::display));
} }
for extension in extensions { let is_extension_available = |ext: &mut Extension| -> bool {
if let Some(available_version) = available_extension_names.get(&extension.name) if available_extensions
&& *available_version >= extension.version .iter()
.any(|inst_ext| inst_ext.extension_name_as_c_str() == Ok(ext.name))
{ {
out_extensions.insert(extension); true
} else { } else {
unsupported_extensions.insert(extension); tracing::warn!(
"Extension {:?} v{} was requested but is not available",
ext.name,
ext.version
);
false
} }
}
for extension in wsi_extensions {
if let Some(available_version) = available_extension_names.get(&extension.name)
&& *available_version >= extension.version
{
out_extensions.insert(extension);
}
// don't warn about missing WSI extensions, these might not all
// be needed and weren't requested by the user.
}
// if a display handle is provided, ensure the required WSI extensions are present
let required_extension_names = display_handle
.map(ash_window::enumerate_required_extensions)
.unwrap_or(Ok(&[]))?;
for &extension in required_extension_names {
let extension = core::ffi::CStr::from_ptr(extension);
let extension = Extension {
name: extension.to_str()?,
version: 0,
}; };
if let Some(available_version) = available_extension_names.get(&extension.name) let mut enabled_extensions = extensions
&& *available_version >= extension.version .extract_if(.., is_extension_available)
{ .collect::<Vec<_>>();
out_extensions.insert(extension);
} else { enabled_extensions.extend(wsi_extensions.extract_if(.., is_extension_available));
unsupported_extensions.insert(extension);
} // if a display handle is provided, ensure the required WSI extensions are present
if let Some(display_handle) = display_handle {
let mut required_extensions = ash_window::enumerate_required_extensions(display_handle)?
.iter()
.map(|&p| Extension {
name: unsafe { CStr::from_ptr(p) },
version: 0,
})
// filter out extensions that are already enabled
.filter(|ext| {
!enabled_extensions
.iter()
.any(|enabled| enabled.name == ext.name)
})
.collect::<Vec<_>>();
// filter out extensions that aren't available, and log a warning for them
let display_extensions = required_extensions.extract_if(.., is_extension_available);
enabled_extensions.extend(display_extensions);
extensions.extend(required_extensions);
} }
// all extensions remaining in `extensions` at this point are unsupported,
// and were requested by the user or are required by the display handle
let unsupported_extensions = HashSet::from_iter(extensions);
let out_extensions = HashSet::from_iter(enabled_extensions);
Ok((out_extensions, unsupported_extensions)) Ok((out_extensions, unsupported_extensions))
} }
}
fn get_layers<'a>( /// returns a list of enabled, or a tuple of enabled and unsupported but requested layers.
pub(crate) fn get_layers<'a>(
entry: &ash::Entry, entry: &ash::Entry,
wants_layers: impl Iterator<Item = &'a CStr> + 'a, wants_layers: Vec<&'a CStr>,
) -> core::result::Result<Vec<&'a CStr>, (Vec<&'a CStr>, Vec<&'a CStr>)> { ) -> core::result::Result<Vec<&'a CStr>, (Vec<&'a CStr>, Vec<&'a CStr>)> {
unsafe { unsafe {
let wants_layers = wants_layers.collect::<Vec<_>>(); let Ok(available_layers) = entry.enumerate_instance_layer_properties() else {
return Err((vec![], wants_layers));
};
let available_layers = entry let Ok(available_layer_names) = available_layers
.enumerate_instance_layer_properties()
.map_err(|_| (Vec::<&'a CStr>::new(), wants_layers.clone()))?;
let available_layer_names = available_layers
.iter() .iter()
.map(|layer| layer.layer_name_as_c_str()) .map(|layer| layer.layer_name_as_c_str())
.collect::<core::result::Result<BTreeSet<_>, _>>() .collect::<core::result::Result<BTreeSet<_>, _>>()
.map_err(|_| (Vec::<&'a CStr>::new(), wants_layers.clone()))?; else {
return Err((vec![], wants_layers));
};
tracing::debug!( tracing::debug!(
"Available layers: {:?}", "Available layers: {:?}",
@ -655,22 +671,21 @@ impl DeviceBuilder {
.collect::<Vec<_>>() .collect::<Vec<_>>()
); );
let mut out_layers = Vec::new(); let mut enabled_layers = Vec::new();
let mut unsupported_layers = Vec::new(); let mut unsupported_layers = Vec::new();
for layer in wants_layers { for layer in wants_layers {
if available_layer_names.contains(&layer) { if available_layer_names.contains(&layer) {
out_layers.push(layer); enabled_layers.push(layer);
} else { } else {
unsupported_layers.push(layer); unsupported_layers.push(layer);
} }
} }
if !unsupported_layers.is_empty() { if !unsupported_layers.is_empty() {
Err((out_layers, unsupported_layers)) Err((enabled_layers, unsupported_layers))
} else { } else {
Ok(out_layers) Ok(enabled_layers)
}
} }
} }
} }
@ -733,92 +748,18 @@ impl Device {
}) })
} }
pub fn new_from_desc(desc: DeviceDesc) -> crate::Result<Self> { pub fn new_from_desc(desc: DeviceDesc) -> crate::Result<Self> {
tracing::debug!("creating new device with: {desc:#?}"); let instance = Instance::new(&crate::instance::InstanceDesc {
let entry = unsafe { ash::Entry::load()? }; app_name: desc.app_name,
app_version: desc.app_version,
let app_name = desc instance_extensions: &desc
.app_name .instance_extensions
.and_then(|name| CString::new(name).ok())
.unwrap_or(c"ShooterGame".to_owned());
let app_info = vk::ApplicationInfo::default()
.api_version(desc.features.version)
.application_name(&app_name)
.application_version(desc.app_version)
.engine_name(c"VidyaEngine")
.engine_version(vk::make_api_version(0, 0, 1, 0));
let mut validation_info =
vk::LayerSettingsCreateInfoEXT::default().settings(desc.layer_settings);
let extra_instance_extensions = [
make_extention!(ext::debug_utils as 1),
#[cfg(debug_assertions)]
make_extention!(ext::layer_settings),
];
let layers = DeviceBuilder::get_layers(&entry, desc.layers.iter().cloned()).unwrap();
let (extensions, unsupported_extensions) = DeviceBuilder::get_extensions(
&entry,
&layers,
desc.instance_extensions
.iter() .iter()
.cloned() .map(|ext| ext.name)
.chain(extra_instance_extensions), .collect::<Vec<_>>(),
desc.display_handle, layers: desc.layers,
)?; layer_settings: desc.layer_settings,
display_handle: desc.display_handle,
if !unsupported_extensions.is_empty() { })?;
tracing::error!(
"extensions were requested but not supported by instance: {:?}",
unsupported_extensions
);
}
let layers = VkNameList::from_strs(&layers);
let extensions = crate::util::CStringList::from_iter(extensions.iter().map(|ext| ext.name));
let create_info = vk::InstanceCreateInfo::default()
.application_info(&app_info)
.enabled_extension_names(&extensions.strings)
.enabled_layer_names(&layers.names)
.push_next(&mut validation_info);
tracing::debug!(
"Creating instance:\napp_info: {app_info:#?}\ncreate_info: {create_info:#?}"
);
let instance = unsafe { entry.create_instance(&create_info, None)? };
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 instance = ext::debug_utils::Instance::new(&entry, &instance);
let messenger = unsafe { instance.create_debug_utils_messenger(&debug_info, None)? };
crate::DebugUtils {
instance,
messenger,
}
};
let instance = Arc::new(Instance {
raw: instance,
_debug_utils: debug_utils,
entry,
});
let mut features = desc.features.with_extension2(make_extention_properties( let mut features = desc.features.with_extension2(make_extention_properties(
khr::swapchain::NAME, khr::swapchain::NAME,
@ -836,7 +777,7 @@ impl Device {
// additionally, pdev would have to be derived from a device and not a scoring function. // additionally, pdev would have to be derived from a device and not a scoring function.
let pdev = DeviceBuilder::choose_physical_device( let pdev = DeviceBuilder::choose_physical_device(
&instance, &instance.inner,
desc.display_handle, desc.display_handle,
&features, &features,
vec![Box::new( vec![Box::new(
@ -845,13 +786,13 @@ impl Device {
)?; )?;
tracing::trace!("pdev: {pdev:?}"); tracing::trace!("pdev: {pdev:?}");
let device = Device::new(instance.clone(), pdev, features)?; let device = Device::new(instance.inner.clone(), pdev, features)?;
Ok(device) Ok(device)
} }
pub fn new( pub fn new(
instance: Arc<Instance>, instance: Arc<InstanceInner>,
physical: PhysicalDevice, physical: PhysicalDevice,
mut features: crate::PhysicalDeviceFeatures, mut features: crate::PhysicalDeviceFeatures,
) -> VkResult<Self> { ) -> VkResult<Self> {
@ -953,7 +894,7 @@ impl Device {
pub fn dev(&self) -> &ash::Device { pub fn dev(&self) -> &ash::Device {
&self.0.device &self.0.device
} }
pub fn instance(&self) -> &Arc<Instance> { pub fn instance(&self) -> &Arc<InstanceInner> {
&self.0.instance &self.0.instance
} }
pub fn swapchain(&self) -> &khr::swapchain::Device { pub fn swapchain(&self) -> &khr::swapchain::Device {

View file

@ -1 +1,172 @@
use std::{
ffi::{CStr, CString},
sync::Arc,
};
use ash::{Entry, ext, vk};
use raw_window_handle::RawDisplayHandle;
use crate::{
device::{Extension, get_extensions, get_layers},
make_extension,
};
pub struct DebugUtilsCreateInfo {
pub severity: vk::DebugUtilsMessageSeverityFlagsEXT,
pub message_type: vk::DebugUtilsMessageTypeFlagsEXT,
}
pub struct InstanceInner {
pub raw: ash::Instance,
pub entry: Entry,
pub(crate) _debug_utils: DebugUtils,
}
#[derive(Clone)]
pub struct Instance {
pub(crate) inner: Arc<InstanceInner>,
}
impl core::fmt::Debug for Instance {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Instance")
.field("raw", &self.inner.raw.handle())
.finish_non_exhaustive()
}
}
pub struct InstanceDesc<'a> {
pub app_name: Option<&'a str>,
pub app_version: u32,
pub instance_extensions: &'a [&'a CStr],
pub layer_settings: &'a [vk::LayerSettingEXT<'a>],
pub layers: &'a [&'a CStr],
pub display_handle: Option<RawDisplayHandle>,
}
impl Instance {
pub fn new<'a>(desc: &InstanceDesc<'a>) -> crate::Result<Self> {
let entry = unsafe { ash::Entry::load()? };
let app_name = desc
.app_name
.and_then(|name| CString::new(name).ok())
.unwrap_or(c"ShooterGame".to_owned());
let version =
unsafe { entry.try_enumerate_instance_version()? }.unwrap_or(vk::API_VERSION_1_0);
let app_info = vk::ApplicationInfo::default()
.api_version(if version < vk::API_VERSION_1_1 {
vk::API_VERSION_1_0
} else {
// ash doesn't support 1.4 yet
vk::API_VERSION_1_3
})
.application_name(&app_name)
.application_version(desc.app_version)
.engine_name(c"Bevy Engine")
.engine_version(vk::make_api_version(0, 0, 1, 0));
let mut validation_info =
vk::LayerSettingsCreateInfoEXT::default().settings(desc.layer_settings);
let layers = match get_layers(&entry, desc.layers.to_vec()) {
Ok(layers) => layers,
Err((supported, unsupported)) => {
tracing::error!(
"Some requested layers were not supported by instance:\nSupported: {:?}\nUnsupported: {:?}",
supported,
unsupported
);
supported
}
};
let mut requested_extensions = desc
.instance_extensions
.iter()
.map(|name| Extension { name, version: 0 })
.collect::<Vec<_>>();
requested_extensions.push(make_extension!(ext::debug_utils as 1));
#[cfg(debug_assertions)]
requested_extensions.push(make_extension!(ext::layer_settings));
let (extensions, unsupported_extensions) =
get_extensions(&entry, &layers, requested_extensions, desc.display_handle)?;
if !unsupported_extensions.is_empty() {
tracing::error!(
"extensions were requested but not supported by instance: {:?}",
unsupported_extensions
);
}
let layers = layers
.iter()
.map(|layer| layer.as_ptr())
.collect::<Vec<_>>();
let extensions = extensions
.iter()
.map(|ext| ext.name.as_ptr())
.collect::<Vec<_>>();
let create_info = vk::InstanceCreateInfo::default()
.application_info(&app_info)
.enabled_extension_names(&extensions)
.enabled_layer_names(&layers)
.push_next(&mut validation_info);
tracing::debug!(
"Creating instance:\napp_info: {app_info:#?}\ncreate_info: {create_info:#?}"
);
let instance = unsafe { entry.create_instance(&create_info, None)? };
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 instance = ext::debug_utils::Instance::new(&entry, &instance);
let messenger = unsafe { instance.create_debug_utils_messenger(&debug_info, None)? };
crate::DebugUtils {
instance,
messenger,
}
};
let instance = Arc::new(InstanceInner {
raw: instance,
_debug_utils: debug_utils,
entry,
});
Ok(Self { inner: instance })
}
}
pub(crate) struct DebugUtils {
pub instance: ext::debug_utils::Instance,
pub messenger: vk::DebugUtilsMessengerEXT,
}
impl Drop for DebugUtils {
fn drop(&mut self) {
unsafe {
self.instance
.destroy_debug_utils_messenger(self.messenger, None);
}
}
}

View file

@ -435,30 +435,8 @@ pub struct PhysicalDevice {
properties: PhysicalDeviceProperties, properties: PhysicalDeviceProperties,
} }
struct DebugUtils { pub(crate) use instance::DebugUtils;
instance: ext::debug_utils::Instance, pub use instance::{DebugUtilsCreateInfo, Instance};
messenger: vk::DebugUtilsMessengerEXT,
}
impl Drop for DebugUtils {
fn drop(&mut self) {
unsafe {
self.instance
.destroy_debug_utils_messenger(self.messenger, None);
}
}
}
pub struct DebugUtilsCreateInfo {
pub severity: vk::DebugUtilsMessageSeverityFlagsEXT,
pub message_type: vk::DebugUtilsMessageTypeFlagsEXT,
}
pub struct Instance {
entry: Entry,
raw: ash::Instance,
_debug_utils: DebugUtils,
}
pub struct SamplerCache { pub struct SamplerCache {
device: Device, device: Device,

View file

@ -17,7 +17,9 @@ use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use crate::{ use crate::{
Instance, Result, define_device_owned_handle, Instance, Result, define_device_owned_handle,
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
images, sync, images,
instance::InstanceInner,
sync,
util::RawMutexGuard, util::RawMutexGuard,
}; };
@ -40,7 +42,7 @@ impl Drop for Surface {
impl Surface { impl Surface {
#[allow(dead_code)] #[allow(dead_code)]
pub fn headless(instance: &Arc<Instance>) -> Result<Self> { pub fn headless(instance: &Arc<InstanceInner>) -> Result<Self> {
let headless_instance = let headless_instance =
ash::ext::headless_surface::Instance::new(&instance.entry, &instance.raw); ash::ext::headless_surface::Instance::new(&instance.entry, &instance.raw);
let functor = khr::surface::Instance::new(&instance.entry, &instance.raw); let functor = khr::surface::Instance::new(&instance.entry, &instance.raw);
@ -67,7 +69,7 @@ impl Surface {
/// was created with the appropriate platform-specific surface extensions /// was created with the appropriate platform-specific surface extensions
/// enabled. /// enabled.
pub unsafe fn new_from_raw_window_handle( pub unsafe fn new_from_raw_window_handle(
instance: &Arc<Instance>, instance: &Arc<InstanceInner>,
display_handle: RawDisplayHandle, display_handle: RawDisplayHandle,
window_handle: RawWindowHandle, window_handle: RawWindowHandle,
) -> Result<Self> { ) -> Result<Self> {
@ -704,7 +706,7 @@ impl WindowSurface {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::device; use crate::make_extension;
use super::*; use super::*;
@ -712,14 +714,8 @@ mod tests {
let device = Device::new_from_default_desc( let device = Device::new_from_default_desc(
None, None,
&[ &[
device::Extension { make_extension!(ash::ext::headless_surface),
name: "VK_EXT_headless_surface", make_extension!(ash::khr::surface),
version: ash::ext::headless_surface::SPEC_VERSION,
},
device::Extension {
name: "VK_KHR_surface",
version: ash::khr::surface::SPEC_VERSION,
},
], ],
)?; )?;