use crate::vk_ffi as vk;
use crate::{GpuError, Result};
type Gipa = unsafe extern "system" fn(vk::Instance, *const u8) -> vk::Pfn;
pub(crate) const LOADER: &str = if cfg!(windows) {
"vulkan-1.dll"
} else if cfg!(target_os = "android") {
"libvulkan.so"
} else {
"libvulkan.so.1"
};
#[cfg_attr(not(windows), allow(dead_code))]
pub(crate) struct Lib {
#[cfg(any(windows, jfgui_glibc, target_os = "android"))]
module: isize,
gipa: Gipa,
}
unsafe impl Send for Lib {}
unsafe impl Sync for Lib {}
impl Lib {
pub fn gipa(&self, instance: vk::Instance, name: &[u8]) -> vk::Pfn {
debug_assert!(name.last() == Some(&0));
unsafe { (self.gipa)(instance, name.as_ptr()) }
}
}
#[cfg(windows)]
mod win {
#[link(name = "kernel32", kind = "raw-dylib")]
unsafe extern "system" {
pub fn LoadLibraryExW(name: *const u16, file: isize, flags: u32) -> isize;
pub fn GetProcAddress(module: isize, name: *const u8) -> usize;
pub fn FreeLibrary(module: isize) -> i32;
pub fn SetThreadErrorMode(mode: u32, old: *mut u32) -> i32;
}
pub const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: u32 = 0x100;
pub const LOAD_LIBRARY_SEARCH_SYSTEM32: u32 = 0x800;
pub const SEM_QUIET: u32 = 0x8003; }
#[cfg(windows)]
impl Lib {
pub fn open(name: &str) -> Result<Lib> {
use alloc::vec::Vec;
let path = name.contains('\\') || name.contains('/');
let wide: Vec<u16> = name.encode_utf16().chain(core::iter::once(0)).collect();
let flags = if path {
win::LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | win::LOAD_LIBRARY_SEARCH_SYSTEM32
} else {
win::LOAD_LIBRARY_SEARCH_SYSTEM32
};
let mut old = 0u32;
let module = unsafe {
win::SetThreadErrorMode(win::SEM_QUIET, &mut old);
let m = win::LoadLibraryExW(wide.as_ptr(), 0, flags);
win::SetThreadErrorMode(old, core::ptr::null_mut());
m
};
if module == 0 {
return Err(GpuError::NoLoader);
}
let p = unsafe { win::GetProcAddress(module, b"vkGetInstanceProcAddr\0".as_ptr()) };
if p == 0 {
unsafe { win::FreeLibrary(module) };
return Err(GpuError::NoLoader);
}
let gipa = unsafe { core::mem::transmute::<usize, Gipa>(p) };
Ok(Lib { module, gipa })
}
}
#[cfg(windows)]
impl Drop for Lib {
fn drop(&mut self) {
unsafe { win::FreeLibrary(self.module) };
}
}
#[cfg(any(jfgui_glibc, target_os = "android"))]
impl Lib {
pub fn open(name: &str) -> Result<Lib> {
let module = plat::dl_open(name).ok_or(GpuError::NoLoader)?;
let p = plat::dl_sym(module, b"vkGetInstanceProcAddr\0");
if p == 0 {
plat::dl_close(module);
return Err(GpuError::NoLoader);
}
let gipa = unsafe { core::mem::transmute::<usize, Gipa>(p) };
Ok(Lib { module: module as isize, gipa })
}
}
#[cfg(any(jfgui_glibc, target_os = "android"))]
impl Drop for Lib {
fn drop(&mut self) {
plat::dl_close(self.module as usize);
}
}
#[cfg(not(any(windows, jfgui_glibc, target_os = "android")))]
impl Lib {
pub fn open(_name: &str) -> Result<Lib> {
Err(GpuError::NoLoader)
}
}