Skip to content

Commit

Permalink
device,instance: Provide load_with() constructor for get_proc_addr …
Browse files Browse the repository at this point in the history
…closure

While working on a GStreamer Vulkan interop example (where
GStreamer-Vulkan opens the ICD and creates most objects for us, which
need to be imported in an `ash::Instance` and `ash::Device`), it wasn't
feasible to construct a `vk::EntryFnV1_0` and `vk::InstanceFnV1_0` with
`extern` functions while keeping object data in some global static,
especially `vk::InstanceFnV1_0` which contains many more functions that
are not consumed by `Instance::load()`. GStreamer provides function
loaders directly on its `GstVulkanInstance` and `GstVulkanDevice` which
are desired to be used rather than attempting to open the same ICD and
loading the same functions by hand.
The  original `Device::load()` and `Instance::load()` already create a
closure internally, which is exactly what we need to expose to have a
single callback that can hold the `&gst_vulkan::VulkanInstance/Device`
state, and respond to a char-pointer name with a function pointer.

Note that this doesn't map very clearly to `Entry`, where the `load()`
constructor is named `from_static_fn()` and a closure signature is
equally lacking.  This is due `Entry` also storing `StaticFn` for
various uses, which any constructor with just a closure won't (easily)
be able to replicate.
  • Loading branch information
MarijnS95 committed Mar 24, 2024
1 parent e31bc45 commit d23282b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 16 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `descriptor_count()` setter on `ash::vk::WriteDescriptorSet` (#809)
- Added `*_as_c_str()` getters for `c_char` pointers and `c_char` arrays (#831)
- Added `#[must_use]` to Vulkan structs to make it more clear that they are moved by the builder pattern (#845)
- Added `load_with()` function on `Device` and `Instance` for providing custom `get_xxx_proc_addr()` implementations (#846)
- Added `Send`/`Sync` to all Vulkan structs (#869)

### Changed
Expand Down
24 changes: 16 additions & 8 deletions ash/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
use crate::prelude::*;
use crate::vk;
use crate::RawPtr;
use core::ffi;
use std::mem;
use std::os::raw::c_void;
use std::ptr;

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDevice.html>
Expand All @@ -19,16 +19,24 @@ pub struct Device {

impl Device {
pub unsafe fn load(instance_fn: &vk::InstanceFnV1_0, device: vk::Device) -> Self {
let load_fn = |name: &std::ffi::CStr| {
mem::transmute((instance_fn.get_device_proc_addr)(device, name.as_ptr()))
};
Self::load_with(
|name: &std::ffi::CStr| {
mem::transmute((instance_fn.get_device_proc_addr)(device, name.as_ptr()))
},
device,
)
}

pub unsafe fn load_with(
mut load_fn: impl FnMut(&ffi::CStr) -> *const ffi::c_void,
device: vk::Device,
) -> Self {
Self::from_parts_1_3(
device,
vk::DeviceFnV1_0::load(load_fn),
vk::DeviceFnV1_1::load(load_fn),
vk::DeviceFnV1_2::load(load_fn),
vk::DeviceFnV1_3::load(load_fn),
vk::DeviceFnV1_0::load(&mut load_fn),
vk::DeviceFnV1_1::load(&mut load_fn),
vk::DeviceFnV1_2::load(&mut load_fn),
vk::DeviceFnV1_3::load(&mut load_fn),
)
}

Expand Down
22 changes: 14 additions & 8 deletions ash/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::device::Device;
use crate::prelude::*;
use crate::vk;
use crate::RawPtr;
use core::ffi;
use std::mem;
use std::os::raw::c_char;
use std::ptr;

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkInstance.html>
Expand All @@ -20,15 +20,21 @@ pub struct Instance {

impl Instance {
pub unsafe fn load(static_fn: &vk::StaticFn, instance: vk::Instance) -> Self {
let load_fn = |name: &std::ffi::CStr| {
mem::transmute((static_fn.get_instance_proc_addr)(instance, name.as_ptr()))
};
Self::load_with(
|name| mem::transmute((static_fn.get_instance_proc_addr)(instance, name.as_ptr())),
instance,
)
}

pub unsafe fn load_with(
mut load_fn: impl FnMut(&ffi::CStr) -> *const ffi::c_void,
instance: vk::Instance,
) -> Self {
Self::from_parts_1_3(
instance,
vk::InstanceFnV1_0::load(load_fn),
vk::InstanceFnV1_1::load(load_fn),
vk::InstanceFnV1_3::load(load_fn),
vk::InstanceFnV1_0::load(&mut load_fn),
vk::InstanceFnV1_1::load(&mut load_fn),
vk::InstanceFnV1_3::load(&mut load_fn),
)
}

Expand Down Expand Up @@ -374,7 +380,7 @@ impl Instance {
pub unsafe fn get_device_proc_addr(
&self,
device: vk::Device,
p_name: *const c_char,
p_name: *const ffi::c_char,
) -> vk::PFN_vkVoidFunction {
(self.instance_fn_1_0.get_device_proc_addr)(device, p_name)
}
Expand Down

0 comments on commit d23282b

Please sign in to comment.