diff --git a/crates/renderer/Cargo.toml b/crates/renderer/Cargo.toml index 30d8faa..f94f238 100644 --- a/crates/renderer/Cargo.toml +++ b/crates/renderer/Cargo.toml @@ -27,3 +27,4 @@ egui = { workspace = true , features = ["bytemuck"]} egui_winit_platform = { workspace = true } bytemuck = { version = "1.21.0", features = ["derive"] } indexmap = "2.7.0" +itertools = "0.14.0" diff --git a/crates/renderer/src/lib.rs b/crates/renderer/src/lib.rs index 8a4b667..35d8465 100644 --- a/crates/renderer/src/lib.rs +++ b/crates/renderer/src/lib.rs @@ -1163,18 +1163,35 @@ impl Vulkan { let mut validation_info = vk::LayerSettingsCreateInfoEXT::default().settings(&validation_settings); - let layers = Self::get_layers(&entry, &[Self::VALIDATION_LAYER_NAME]).unwrap(); - - // optional display handle - let extensions = Self::get_extensions( + let layers = Self::get_layers( &entry, - &layers, - // &[ash::ext::debug_utils::NAME, ash::ext::layer_settings::NAME], - &[ash::ext::debug_utils::NAME], - display_handle, + instance_layers + .into_iter() + .chain(&[ + #[cfg(debug_assertions)] + Self::VALIDATION_LAYER_NAME, + ]) + .cloned(), ) .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 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>( entry: &ash::Entry, layers: &[&'a CStr], - extensions: &[&'a CStr], + extensions: impl Iterator + 'a, display_handle: Option, - ) -> core::result::Result, (Vec<&'a CStr>, Vec<&'a CStr>)> { + ) -> Result<(Vec<&'a CStr>, Vec<&'a CStr>)> { unsafe { - let available_extensions = Self::get_available_extensions(entry, layers) - .map_err(|_| (Vec::<&'a CStr>::new(), extensions.to_vec()))?; + let available_extensions = Self::get_available_extensions(entry, layers)?; let available_extension_names = available_extensions .iter() - .map(|layer| layer.extension_name_as_c_str()) - .collect::, _>>() - .map_err(|_| (Vec::<&'a CStr>::new(), extensions.to_vec()))?; + .filter_map(|layer| layer.extension_name_as_c_str().ok()) + .collect::>(); - let mut out_extensions = Vec::with_capacity(extensions.len()); - let mut unsupported_extensions = Vec::with_capacity(extensions.len()); - for &extension in extensions { - if available_extension_names.contains(&extension) { + let mut out_extensions = Vec::new(); + let mut unsupported_extensions = Vec::new(); + + for extension in extensions { + if available_extension_names.contains(extension) { out_extensions.push(extension); } else { 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)) - .unwrap_or(Ok(&[])) - else { - return Err((out_extensions, unsupported_extensions)); - }; + .unwrap_or(Ok(&[]))?; for &extension in required_extension_names { let extension = core::ffi::CStr::from_ptr(extension); @@ -1622,31 +1636,30 @@ impl Vulkan { } } - if !unsupported_extensions.is_empty() { - Err((out_extensions, unsupported_extensions)) - } else { - Ok(out_extensions) - } + Ok((out_extensions, unsupported_extensions)) } } fn get_layers<'a>( entry: &ash::Entry, - wants_layers: &[&'a CStr], + wants_layers: impl Iterator + 'a, ) -> core::result::Result, (Vec<&'a CStr>, Vec<&'a CStr>)> { unsafe { + let wants_layers = wants_layers.collect::>(); + let available_layers = entry .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 .iter() .map(|layer| layer.layer_name_as_c_str()) .collect::, _>>() - .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 unsupported_layers = Vec::with_capacity(wants_layers.len()); - for &layer in wants_layers { + let mut out_layers = Vec::new(); + let mut unsupported_layers = Vec::new(); + + for layer in wants_layers { if available_layer_names.contains(&layer) { out_layers.push(layer); } else {