Skip to content

Commit 0d61648

Browse files
Vecveccwfitzgerald
andauthored
Allow enabling additional vulkan extensions in Adapter::open and Instance::init (#7829)
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
1 parent 208fe4c commit 0d61648

File tree

4 files changed

+151
-34
lines changed

4 files changed

+151
-34
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ Bottom level categories:
5959
- Add acceleration structure limits. By @Vecvec in [#7845](https://github.com/gfx-rs/wgpu/pull/7845).
6060
- Add support for clip-distances feature for Vulkan and GL backends. By @dzamkov in [#7730](https://github.com/gfx-rs/wgpu/pull/7730)
6161

62+
#### Vulkan
63+
64+
- 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).
65+
6266
### Bug Fixes
6367

6468
#### General

wgpu-hal/src/vulkan/adapter.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use alloc::{borrow::ToOwned as _, collections::BTreeMap, sync::Arc, vec::Vec};
2-
use core::ffi::CStr;
1+
use alloc::{borrow::ToOwned as _, boxed::Box, collections::BTreeMap, sync::Arc, vec::Vec};
2+
use core::{ffi::CStr, marker::PhantomData};
33

44
use ash::{ext, google, khr, vk};
55
use parking_lot::Mutex;
@@ -2287,25 +2287,37 @@ impl super::Adapter {
22872287
pub fn texture_format_as_raw(&self, texture_format: wgt::TextureFormat) -> vk::Format {
22882288
self.private_caps.map_texture_format(texture_format)
22892289
}
2290-
}
2291-
2292-
impl crate::Adapter for super::Adapter {
2293-
type A = super::Api;
22942290

2295-
unsafe fn open(
2291+
/// # Safety:
2292+
/// - Same as `open` plus
2293+
/// - The callback may not change anything that the device does not support.
2294+
/// - The callback may not remove features.
2295+
pub unsafe fn open_with_callback<'a>(
22962296
&self,
22972297
features: wgt::Features,
2298-
_limits: &wgt::Limits,
22992298
memory_hints: &wgt::MemoryHints,
2299+
callback: Option<Box<super::CreateDeviceCallback<'a>>>,
23002300
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
2301-
let enabled_extensions = self.required_device_extensions(features);
2301+
let mut enabled_extensions = self.required_device_extensions(features);
23022302
let mut enabled_phd_features = self.physical_device_features(&enabled_extensions, features);
23032303

23042304
let family_index = 0; //TODO
23052305
let family_info = vk::DeviceQueueCreateInfo::default()
23062306
.queue_family_index(family_index)
23072307
.queue_priorities(&[1.0]);
2308-
let family_infos = [family_info];
2308+
let mut family_infos = Vec::from([family_info]);
2309+
2310+
let mut pre_info = vk::DeviceCreateInfo::default();
2311+
2312+
if let Some(callback) = callback {
2313+
callback(super::CreateDeviceCallbackArgs {
2314+
extensions: &mut enabled_extensions,
2315+
device_features: &mut enabled_phd_features,
2316+
queue_create_infos: &mut family_infos,
2317+
create_info: &mut pre_info,
2318+
_phantom: PhantomData,
2319+
})
2320+
}
23092321

23102322
let str_pointers = enabled_extensions
23112323
.iter()
@@ -2315,7 +2327,7 @@ impl crate::Adapter for super::Adapter {
23152327
})
23162328
.collect::<Vec<_>>();
23172329

2318-
let pre_info = vk::DeviceCreateInfo::default()
2330+
let pre_info = pre_info
23192331
.queue_create_infos(&family_infos)
23202332
.enabled_extension_names(&str_pointers);
23212333
let info = enabled_phd_features.add_to_device_create(pre_info);
@@ -2351,6 +2363,19 @@ impl crate::Adapter for super::Adapter {
23512363
)
23522364
}
23532365
}
2366+
}
2367+
2368+
impl crate::Adapter for super::Adapter {
2369+
type A = super::Api;
2370+
2371+
unsafe fn open(
2372+
&self,
2373+
features: wgt::Features,
2374+
_limits: &wgt::Limits,
2375+
memory_hints: &wgt::MemoryHints,
2376+
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
2377+
unsafe { self.open_with_callback(features, memory_hints, None) }
2378+
}
23542379

23552380
unsafe fn texture_format_capabilities(
23562381
&self,

wgpu-hal/src/vulkan/instance.rs

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use alloc::{borrow::ToOwned as _, boxed::Box, ffi::CString, string::String, sync::Arc, vec::Vec};
22
use core::{
33
ffi::{c_void, CStr},
4+
marker::PhantomData,
45
slice,
56
str::FromStr,
67
};
@@ -585,27 +586,19 @@ impl super::Instance {
585586
swapchain: RwLock::new(None),
586587
}
587588
}
588-
}
589-
590-
impl Drop for super::InstanceShared {
591-
fn drop(&mut self) {
592-
unsafe {
593-
// Keep du alive since destroy_instance may also log
594-
let _du = self.debug_utils.take().inspect(|du| {
595-
du.extension
596-
.destroy_debug_utils_messenger(du.messenger, None);
597-
});
598-
if self.drop_guard.is_none() {
599-
self.raw.destroy_instance(None);
600-
}
601-
}
602-
}
603-
}
604-
605-
impl crate::Instance for super::Instance {
606-
type A = super::Api;
607589

608-
unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
590+
/// `Instance::init` but with a callback.
591+
/// If you want to add extensions, add the to the `Vec<'static CStr>` not the create info, otherwise
592+
/// it will be overwritten
593+
///
594+
/// # Safety:
595+
/// Same as `init` but additionally
596+
/// - Callback must not remove features.
597+
/// - Callback must not change anything to what the instance does not support.
598+
pub unsafe fn init_with_callback(
599+
desc: &crate::InstanceDescriptor,
600+
callback: Option<Box<super::CreateInstanceCallback>>,
601+
) -> Result<Self, crate::InstanceError> {
609602
profiling::scope!("Init Vulkan Backend");
610603

611604
let entry = unsafe {
@@ -654,7 +647,17 @@ impl crate::Instance for super::Instance {
654647
},
655648
);
656649

657-
let extensions = Self::desired_extensions(&entry, instance_api_version, desc.flags)?;
650+
let mut extensions = Self::desired_extensions(&entry, instance_api_version, desc.flags)?;
651+
let mut create_info = vk::InstanceCreateInfo::default();
652+
653+
if let Some(callback) = callback {
654+
callback(super::CreateInstanceCallbackArgs {
655+
extensions: &mut extensions,
656+
create_info: &mut create_info,
657+
entry: &entry,
658+
_phantom: PhantomData,
659+
});
660+
}
658661

659662
let instance_layers = {
660663
profiling::scope!("vkEnumerateInstanceLayerProperties");
@@ -814,7 +817,7 @@ impl crate::Instance for super::Instance {
814817
})
815818
.collect::<Vec<_>>();
816819

817-
let mut create_info = vk::InstanceCreateInfo::default()
820+
create_info = create_info
818821
.flags(flags)
819822
.application_info(&app_info)
820823
.enabled_layer_names(&str_pointers[..layers.len()])
@@ -876,6 +879,29 @@ impl crate::Instance for super::Instance {
876879
)
877880
}
878881
}
882+
}
883+
884+
impl Drop for super::InstanceShared {
885+
fn drop(&mut self) {
886+
unsafe {
887+
// Keep du alive since destroy_instance may also log
888+
let _du = self.debug_utils.take().inspect(|du| {
889+
du.extension
890+
.destroy_debug_utils_messenger(du.messenger, None);
891+
});
892+
if self.drop_guard.is_none() {
893+
self.raw.destroy_instance(None);
894+
}
895+
}
896+
}
897+
}
898+
899+
impl crate::Instance for super::Instance {
900+
type A = super::Api;
901+
902+
unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
903+
unsafe { Self::init_with_callback(desc, None) }
904+
}
879905

880906
unsafe fn create_surface(
881907
&self,

wgpu-hal/src/vulkan/mod.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ mod semaphore_list;
3636
pub use adapter::PhysicalDeviceFeatures;
3737

3838
use alloc::{boxed::Box, ffi::CString, sync::Arc, vec::Vec};
39-
use core::{borrow::Borrow, ffi::CStr, fmt, mem, num::NonZeroU32};
39+
use core::{borrow::Borrow, ffi::CStr, fmt, marker::PhantomData, mem, num::NonZeroU32};
4040

4141
use arrayvec::ArrayVec;
4242
use ash::{ext, khr, vk};
@@ -1500,3 +1500,65 @@ struct RawTlasInstance {
15001500
shader_binding_table_record_offset_and_flags: u32,
15011501
acceleration_structure_reference: u64,
15021502
}
1503+
1504+
/// Arguments to the [`CreateDeviceCallback`].
1505+
pub struct CreateDeviceCallbackArgs<'arg, 'pnext, 'this>
1506+
where
1507+
'this: 'pnext,
1508+
{
1509+
/// The extensions to enable for the device. You must not remove anything from this list,
1510+
/// but you may add to it.
1511+
pub extensions: &'arg mut Vec<&'static CStr>,
1512+
/// The physical device features to enable. You may enable features, but must not disable any.
1513+
pub device_features: &'arg mut PhysicalDeviceFeatures,
1514+
/// The queue create infos for the device. You may add or modify queue create infos as needed.
1515+
pub queue_create_infos: &'arg mut Vec<vk::DeviceQueueCreateInfo<'pnext>>,
1516+
/// The create info for the device. You may add or modify things in the pnext chain, but
1517+
/// do not turn features off. Additionally, do not add things to the list of extensions,
1518+
/// or to the feature set, as all changes to that member will be overwritten.
1519+
pub create_info: &'arg mut vk::DeviceCreateInfo<'pnext>,
1520+
/// We need to have `'this` in the struct, so we can declare that all lifetimes coming from
1521+
/// captures in the closure will live longer (and hence satisfy) `'pnext`. However, we
1522+
/// don't actually directly use `'this`
1523+
_phantom: PhantomData<&'this ()>,
1524+
}
1525+
1526+
/// Callback to allow changing the vulkan device creation parameters.
1527+
///
1528+
/// # Safety:
1529+
/// - If you want to add extensions, add the to the `Vec<'static CStr>` not the create info,
1530+
/// as the create info value will be overwritten.
1531+
/// - Callback must not remove features.
1532+
/// - Callback must not change anything to what the instance does not support.
1533+
pub type CreateDeviceCallback<'this> =
1534+
dyn for<'arg, 'pnext> FnOnce(CreateDeviceCallbackArgs<'arg, 'pnext, 'this>) + 'this;
1535+
1536+
/// Arguments to the [`CreateInstanceCallback`].
1537+
pub struct CreateInstanceCallbackArgs<'arg, 'pnext, 'this>
1538+
where
1539+
'this: 'pnext,
1540+
{
1541+
/// The extensions to enable for the instance. You must not remove anything from this list,
1542+
/// but you may add to it.
1543+
pub extensions: &'arg mut Vec<&'static CStr>,
1544+
/// The create info for the instance. You may add or modify things in the pnext chain, but
1545+
/// do not turn features off. Additionally, do not add things to the list of extensions,
1546+
/// all changes to that member will be overwritten.
1547+
pub create_info: &'arg mut vk::InstanceCreateInfo<'pnext>,
1548+
/// Vulkan entry point.
1549+
pub entry: &'arg ash::Entry,
1550+
/// We need to have `'this` in the struct, so we can declare that all lifetimes coming from
1551+
/// captures in the closure will live longer (and hence satisfy) `'pnext`. However, we
1552+
/// don't actually directly use `'this`
1553+
_phantom: PhantomData<&'this ()>,
1554+
}
1555+
1556+
/// Callback to allow changing the vulkan instance creation parameters.
1557+
///
1558+
/// # Safety:
1559+
/// - If you want to add extensions, add the to the `Vec<'static CStr>` not the create info,
1560+
/// as the create info value will be overwritten.
1561+
/// - Callback must not remove features.
1562+
/// - Callback must not change anything to what the instance does not support.
1563+
pub type CreateInstanceCallback<'this> =
1564+
dyn for<'arg, 'pnext> FnOnce(CreateInstanceCallbackArgs<'arg, 'pnext, 'this>) + 'this;

0 commit comments

Comments
 (0)