layers/extensions passed to Vulkan::new honored now

also permit extensions to fail being used while still creating a device
This commit is contained in:
Janis 2025-01-01 21:34:18 +01:00
parent a26b0d16db
commit 669a4a0a3f
2 changed files with 49 additions and 35 deletions

View file

@ -27,3 +27,4 @@ egui = { workspace = true , features = ["bytemuck"]}
egui_winit_platform = { workspace = true } egui_winit_platform = { workspace = true }
bytemuck = { version = "1.21.0", features = ["derive"] } bytemuck = { version = "1.21.0", features = ["derive"] }
indexmap = "2.7.0" indexmap = "2.7.0"
itertools = "0.14.0"

View file

@ -1163,18 +1163,35 @@ impl Vulkan {
let mut validation_info = let mut validation_info =
vk::LayerSettingsCreateInfoEXT::default().settings(&validation_settings); vk::LayerSettingsCreateInfoEXT::default().settings(&validation_settings);
let layers = Self::get_layers(&entry, &[Self::VALIDATION_LAYER_NAME]).unwrap(); let layers = Self::get_layers(
// optional display handle
let extensions = Self::get_extensions(
&entry, &entry,
&layers, instance_layers
// &[ash::ext::debug_utils::NAME, ash::ext::layer_settings::NAME], .into_iter()
&[ash::ext::debug_utils::NAME], .chain(&[
display_handle, #[cfg(debug_assertions)]
Self::VALIDATION_LAYER_NAME,
])
.cloned(),
) )
.unwrap(); .unwrap();
let (extensions, unsupported_extensions) = Self::get_extensions(
&entry,
&layers,
instance_extensions
.into_iter()
.chain([ash::ext::debug_utils::NAME, ash::ext::layer_settings::NAME].iter())
.cloned(),
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 layers = VkNameList::from_strs(&layers);
let extensions = VkNameList::from_strs(&extensions); let extensions = VkNameList::from_strs(&extensions);
@ -1580,38 +1597,35 @@ impl Vulkan {
} }
} }
/// returns a tuple of supported/enabled extensions and unsupported/requested extensions
fn get_extensions<'a>( fn get_extensions<'a>(
entry: &ash::Entry, entry: &ash::Entry,
layers: &[&'a CStr], layers: &[&'a CStr],
extensions: &[&'a CStr], extensions: impl Iterator<Item = &'a CStr> + 'a,
display_handle: Option<RawDisplayHandle>, display_handle: Option<RawDisplayHandle>,
) -> core::result::Result<Vec<&'a CStr>, (Vec<&'a CStr>, Vec<&'a CStr>)> { ) -> Result<(Vec<&'a CStr>, Vec<&'a CStr>)> {
unsafe { unsafe {
let available_extensions = Self::get_available_extensions(entry, layers) let available_extensions = Self::get_available_extensions(entry, layers)?;
.map_err(|_| (Vec::<&'a CStr>::new(), extensions.to_vec()))?;
let available_extension_names = available_extensions let available_extension_names = available_extensions
.iter() .iter()
.map(|layer| layer.extension_name_as_c_str()) .filter_map(|layer| layer.extension_name_as_c_str().ok())
.collect::<core::result::Result<BTreeSet<_>, _>>() .collect::<BTreeSet<_>>();
.map_err(|_| (Vec::<&'a CStr>::new(), extensions.to_vec()))?;
let mut out_extensions = Vec::with_capacity(extensions.len()); let mut out_extensions = Vec::new();
let mut unsupported_extensions = Vec::with_capacity(extensions.len()); let mut unsupported_extensions = Vec::new();
for &extension in extensions {
if available_extension_names.contains(&extension) { for extension in extensions {
if available_extension_names.contains(extension) {
out_extensions.push(extension); out_extensions.push(extension);
} else { } else {
unsupported_extensions.push(extension); unsupported_extensions.push(extension);
} }
} }
let Ok(required_extension_names) = display_handle let required_extension_names = display_handle
.map(|display_handle| ash_window::enumerate_required_extensions(display_handle)) .map(|display_handle| ash_window::enumerate_required_extensions(display_handle))
.unwrap_or(Ok(&[])) .unwrap_or(Ok(&[]))?;
else {
return Err((out_extensions, unsupported_extensions));
};
for &extension in required_extension_names { for &extension in required_extension_names {
let extension = core::ffi::CStr::from_ptr(extension); let extension = core::ffi::CStr::from_ptr(extension);
@ -1622,31 +1636,30 @@ impl Vulkan {
} }
} }
if !unsupported_extensions.is_empty() { Ok((out_extensions, unsupported_extensions))
Err((out_extensions, unsupported_extensions))
} else {
Ok(out_extensions)
}
} }
} }
fn get_layers<'a>( fn get_layers<'a>(
entry: &ash::Entry, entry: &ash::Entry,
wants_layers: &[&'a CStr], wants_layers: impl Iterator<Item = &'a CStr> + 'a,
) -> 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 available_layers = entry let available_layers = entry
.enumerate_instance_layer_properties() .enumerate_instance_layer_properties()
.map_err(|_| (Vec::<&'a CStr>::new(), wants_layers.to_vec()))?; .map_err(|_| (Vec::<&'a CStr>::new(), wants_layers.clone()))?;
let available_layer_names = available_layers 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.to_vec()))?; .map_err(|_| (Vec::<&'a CStr>::new(), wants_layers.clone()))?;
let mut out_layers = Vec::with_capacity(wants_layers.len()); let mut out_layers = Vec::new();
let mut unsupported_layers = Vec::with_capacity(wants_layers.len()); 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); out_layers.push(layer);
} else { } else {