Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use libloading instead of shared_library #1947

Merged
merged 1 commit into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion vulkano/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ bytemuck = { version = "1.7", features = ["derive", "extern_crate_std", "min_con
crossbeam-queue = "0.3"
half = "1.8"
lazy_static = "1.4"
libloading = "0.7"
nalgebra = { version = "0.31.0", optional = true }
parking_lot = { version = "0.12", features = ["send_guard"] }
shared_library = "0.1"
smallvec = "1.8"

[build-dependencies]
Expand Down
5 changes: 3 additions & 2 deletions vulkano/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ use std::{
fmt,
fs::File,
hash::{Hash, Hasher},
mem::{self, MaybeUninit},
mem::MaybeUninit,
ops::Deref,
ptr,
sync::{Arc, Mutex, MutexGuard, Weak},
Expand Down Expand Up @@ -394,7 +394,8 @@ impl Device {

// loading the function pointers of the newly-created device
let fns = DeviceFunctions::load(|name| unsafe {
mem::transmute((fns_i.v1_0.get_device_proc_addr)(handle, name.as_ptr()))
(fns_i.v1_0.get_device_proc_addr)(handle, name.as_ptr())
.map_or(ptr::null(), |func| func as _)
});

let device = Arc::new(Device {
Expand Down
6 changes: 5 additions & 1 deletion vulkano/src/instance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,11 @@ impl Instance {

// Loading the function pointers of the newly-created instance.
let fns = {
InstanceFunctions::load(|name| library.get_instance_proc_addr(handle, name.as_ptr()))
InstanceFunctions::load(|name| {
library
.get_instance_proc_addr(handle, name.as_ptr())
.map_or(ptr::null(), |func| func as _)
})
};

let mut instance = Instance {
Expand Down
75 changes: 29 additions & 46 deletions vulkano/src/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,8 @@ use crate::{
instance::{InstanceExtensions, LayerProperties},
Error, OomError, SafeDeref, Success, Version,
};
use shared_library;
use std::{
error,
ffi::{c_void, CStr},
fmt,
mem::transmute,
os::raw::c_char,
path::Path,
ptr,
sync::Arc,
};
use libloading::{Error as LibloadingError, Library};
use std::{error, ffi::CStr, fmt, mem::transmute, os::raw::c_char, path::Path, ptr, sync::Arc};

/// A loaded library containing a valid Vulkan implementation.
#[derive(Debug)]
Expand Down Expand Up @@ -89,7 +80,9 @@ impl VulkanLibrary {
L: Loader + 'static,
{
let fns = EntryFunctions::load(|name| unsafe {
transmute(loader.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr()))
loader
.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr())
.map_or(ptr::null(), |func| func as _)
});

// Per the Vulkan spec:
Expand All @@ -100,18 +93,17 @@ impl VulkanLibrary {
let name = CStr::from_bytes_with_nul_unchecked(b"vkEnumerateInstanceVersion\0");
let func = loader.get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr());

if func.is_null() {
if let Some(func) = func {
let func: ash::vk::PFN_vkEnumerateInstanceVersion = transmute(func);
let mut api_version = 0;
check_errors(func(&mut api_version))?;
Version::from(api_version)
} else {
Version {
major: 1,
minor: 0,
patch: 0,
}
} else {
type Pfn = extern "system" fn(pApiVersion: *mut u32) -> ash::vk::Result;
let func: Pfn = transmute(func);
let mut api_version = 0;
check_errors(func(&mut api_version))?;
Version::from(api_version)
}
};

Expand Down Expand Up @@ -227,11 +219,11 @@ impl VulkanLibrary {

/// Calls `get_instance_proc_addr` on the underlying loader.
#[inline]
pub fn get_instance_proc_addr(
pub unsafe fn get_instance_proc_addr(
&self,
instance: ash::vk::Instance,
name: *const c_char,
) -> *const c_void {
) -> ash::vk::PFN_vkVoidFunction {
self.loader.get_instance_proc_addr(instance, name)
}
}
Expand All @@ -241,11 +233,11 @@ pub unsafe trait Loader: Send + Sync {
/// Calls the `vkGetInstanceProcAddr` function. The parameters are the same.
///
/// The returned function must stay valid for as long as `self` is alive.
fn get_instance_proc_addr(
unsafe fn get_instance_proc_addr(
&self,
instance: ash::vk::Instance,
name: *const c_char,
) -> *const c_void;
) -> ash::vk::PFN_vkVoidFunction;
}

unsafe impl<T> Loader for T
Expand All @@ -254,11 +246,11 @@ where
T::Target: Loader,
{
#[inline]
fn get_instance_proc_addr(
unsafe fn get_instance_proc_addr(
&self,
instance: ash::vk::Instance,
name: *const c_char,
) -> *const c_void {
) -> ash::vk::PFN_vkVoidFunction {
(**self).get_instance_proc_addr(instance, name)
}
}
Expand All @@ -272,9 +264,8 @@ impl fmt::Debug for dyn Loader {

/// Implementation of `Loader` that loads Vulkan from a dynamic library.
pub struct DynamicLibraryLoader {
vk_lib: shared_library::dynamic_library::DynamicLibrary,
get_proc_addr:
extern "system" fn(instance: ash::vk::Instance, pName: *const c_char) -> *const c_void,
vk_lib: Library,
get_instance_proc_addr: ash::vk::PFN_vkGetInstanceProcAddr,
}

impl DynamicLibraryLoader {
Expand All @@ -289,31 +280,27 @@ impl DynamicLibraryLoader {
where
P: AsRef<Path>,
{
let vk_lib = shared_library::dynamic_library::DynamicLibrary::open(Some(path.as_ref()))
.map_err(LoadingError::LibraryLoadFailure)?;
let vk_lib = Library::new(path.as_ref()).map_err(LoadingError::LibraryLoadFailure)?;

let get_proc_addr = {
let ptr: *mut c_void = vk_lib
.symbol("vkGetInstanceProcAddr")
.map_err(|_| LoadingError::MissingEntryPoint("vkGetInstanceProcAddr".to_owned()))?;
transmute(ptr)
};
let get_instance_proc_addr = *vk_lib
.get(b"vkGetInstanceProcAddr")
.map_err(LoadingError::LibraryLoadFailure)?;

Ok(DynamicLibraryLoader {
vk_lib,
get_proc_addr,
get_instance_proc_addr,
})
}
}

unsafe impl Loader for DynamicLibraryLoader {
#[inline]
fn get_instance_proc_addr(
unsafe fn get_instance_proc_addr(
&self,
instance: ash::vk::Instance,
name: *const c_char,
) -> *const c_void {
(self.get_proc_addr)(instance, name)
) -> ash::vk::PFN_vkVoidFunction {
(self.get_instance_proc_addr)(instance, name)
}
}

Expand Down Expand Up @@ -352,13 +339,10 @@ macro_rules! statically_linked_vulkan_loader {
}

/// Error that can happen when loading a Vulkan library.
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum LoadingError {
/// Failed to load the Vulkan shared library.
LibraryLoadFailure(String), // TODO: meh for error type, but this needs changes in shared_library

/// One of the entry points required to be supported by the Vulkan implementation is missing.
MissingEntryPoint(String),
LibraryLoadFailure(LibloadingError),

/// Not enough memory.
OomError(OomError),
Expand All @@ -383,7 +367,6 @@ impl fmt::Display for LoadingError {
"{}",
match *self {
Self::LibraryLoadFailure(_) => "failed to load the Vulkan shared library",
Self::MissingEntryPoint(_) => "one of the entry points required to be supported by the Vulkan implementation is missing",
Self::OomError(_) => "not enough memory available",
}
)
Expand Down