diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac793f787..def3164bf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,10 @@ Bottom level categories: - Add support for [quad operations](https://www.w3.org/TR/WGSL/#quad-builtin-functions) (requires `SUBGROUP` feature to be enabled). By @dzamkov and @valaphee in [#7683](https://github.com/gfx-rs/wgpu/pull/7683). - Add support for `atomicCompareExchangeWeak` in HLSL and GLSL backends. By @cryvosh in [#7658](https://github.com/gfx-rs/wgpu/pull/7658) +#### Vulkan + +- Add ways to initialise the instance and open the adapter with callbacks to add extensions. By @Vecvec in [#7829](https://github.com/gfx-rs/wgpu/pull/7829). + ### Bug Fixes #### General diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index acd32ff6e7..727360b865 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -2271,25 +2271,36 @@ impl super::Adapter { pub fn texture_format_as_raw(&self, texture_format: wgt::TextureFormat) -> vk::Format { self.private_caps.map_texture_format(texture_format) } -} - -impl crate::Adapter for super::Adapter { - type A = super::Api; - unsafe fn open( + /// # Safety: + /// - Same as `open` plus + /// - The callback may not change anything that the device does not support. + /// - The callback may not remove features. + pub unsafe fn open_with_callback<'a>( &self, features: wgt::Features, - _limits: &wgt::Limits, memory_hints: &wgt::MemoryHints, + callback: Option>, ) -> Result, crate::DeviceError> { - let enabled_extensions = self.required_device_extensions(features); + let mut enabled_extensions = self.required_device_extensions(features); let mut enabled_phd_features = self.physical_device_features(&enabled_extensions, features); let family_index = 0; //TODO let family_info = vk::DeviceQueueCreateInfo::default() .queue_family_index(family_index) .queue_priorities(&[1.0]); - let family_infos = [family_info]; + let mut family_infos = Vec::from([family_info]); + + let mut pre_info = vk::DeviceCreateInfo::default(); + + if let Some(callback) = callback { + callback( + &mut enabled_extensions, + &mut enabled_phd_features, + &mut family_infos, + &mut pre_info, + ) + } let str_pointers = enabled_extensions .iter() @@ -2299,7 +2310,7 @@ impl crate::Adapter for super::Adapter { }) .collect::>(); - let pre_info = vk::DeviceCreateInfo::default() + let pre_info = pre_info .queue_create_infos(&family_infos) .enabled_extension_names(&str_pointers); let info = enabled_phd_features.add_to_device_create(pre_info); @@ -2335,6 +2346,19 @@ impl crate::Adapter for super::Adapter { ) } } +} + +impl crate::Adapter for super::Adapter { + type A = super::Api; + + unsafe fn open( + &self, + features: wgt::Features, + _limits: &wgt::Limits, + memory_hints: &wgt::MemoryHints, + ) -> Result, crate::DeviceError> { + unsafe { self.open_with_callback(features, memory_hints, None) } + } unsafe fn texture_format_capabilities( &self, diff --git a/wgpu-hal/src/vulkan/instance.rs b/wgpu-hal/src/vulkan/instance.rs index c3ce109c04..55832ec374 100644 --- a/wgpu-hal/src/vulkan/instance.rs +++ b/wgpu-hal/src/vulkan/instance.rs @@ -585,27 +585,19 @@ impl super::Instance { swapchain: RwLock::new(None), } } -} -impl Drop for super::InstanceShared { - fn drop(&mut self) { - unsafe { - // Keep du alive since destroy_instance may also log - let _du = self.debug_utils.take().inspect(|du| { - du.extension - .destroy_debug_utils_messenger(du.messenger, None); - }); - if self.drop_guard.is_none() { - self.raw.destroy_instance(None); - } - } - } -} - -impl crate::Instance for super::Instance { - type A = super::Api; - - unsafe fn init(desc: &crate::InstanceDescriptor) -> Result { + /// `Instance::init` but with a callback. + /// If you want to add extensions, add the to the `Vec<'static CStr>` not the create info, otherwise + /// it will be overwritten + /// + /// # Safety: + /// Same as `init` but additionally + /// - Callback must not remove features. + /// - Callback must not change anything to what the instance does not support. + pub unsafe fn init_with_callback( + desc: &crate::InstanceDescriptor, + callback: Option, + ) -> Result { profiling::scope!("Init Vulkan Backend"); let entry = unsafe { @@ -654,7 +646,12 @@ impl crate::Instance for super::Instance { }, ); - let extensions = Self::desired_extensions(&entry, instance_api_version, desc.flags)?; + let mut extensions = Self::desired_extensions(&entry, instance_api_version, desc.flags)?; + let mut create_info = vk::InstanceCreateInfo::default(); + + if let Some(callback) = callback { + callback(&mut extensions, &mut create_info, &entry) + } let instance_layers = { profiling::scope!("vkEnumerateInstanceLayerProperties"); @@ -814,7 +811,7 @@ impl crate::Instance for super::Instance { }) .collect::>(); - let mut create_info = vk::InstanceCreateInfo::default() + create_info = create_info .flags(flags) .application_info(&app_info) .enabled_layer_names(&str_pointers[..layers.len()]) @@ -876,6 +873,29 @@ impl crate::Instance for super::Instance { ) } } +} + +impl Drop for super::InstanceShared { + fn drop(&mut self) { + unsafe { + // Keep du alive since destroy_instance may also log + let _du = self.debug_utils.take().inspect(|du| { + du.extension + .destroy_debug_utils_messenger(du.messenger, None); + }); + if self.drop_guard.is_none() { + self.raw.destroy_instance(None); + } + } + } +} + +impl crate::Instance for super::Instance { + type A = super::Api; + + unsafe fn init(desc: &crate::InstanceDescriptor) -> Result { + unsafe { Self::init_with_callback(desc, None) } + } unsafe fn create_surface( &self, diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index 3d4e5cacee..4d20c2e8ac 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -1500,3 +1500,19 @@ struct RawTlasInstance { shader_binding_table_record_offset_and_flags: u32, acceleration_structure_reference: u64, } + +pub type CreateDeviceCallback<'a> = &'a dyn Fn( + &mut Vec<&'static CStr>, + &mut PhysicalDeviceFeatures, + &mut Vec, + &mut vk::DeviceCreateInfo, +); + +pub type CreateInstanceCallback<'a> = &'a dyn Fn( + // extensions + &mut Vec<&'static CStr>, + // create info + &mut vk::InstanceCreateInfo, + // The wgpu loaded entry + &ash::Entry, +);