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 Dec 5, 2023
1 parent befb8cd commit 9e5c1bf
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 15 deletions.
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::c_void;
use std::mem;
use std::os::raw::c_void;
use std::ptr;

/// <https://www.khronos.org/registry/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(&core::ffi::CStr) -> *const 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
20 changes: 13 additions & 7 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::{c_char, c_void};
use std::mem;
use std::os::raw::c_char;
use std::ptr;

/// <https://www.khronos.org/registry/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(&core::ffi::CStr) -> *const 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

0 comments on commit 9e5c1bf

Please sign in to comment.