1 use crate::entry::EntryCustom; 2 use crate::entry::MissingEntryPoint; 3 use libloading::Library; 4 use std::error::Error; 5 use std::ffi::OsStr; 6 use std::fmt; 7 use std::ptr; 8 use std::sync::Arc; 9 10 #[cfg(windows)] 11 const LIB_PATH: &str = "vulkan-1.dll"; 12 13 #[cfg(all( 14 unix, 15 not(any(target_os = "macos", target_os = "ios", target_os = "android")) 16 ))] 17 const LIB_PATH: &str = "libvulkan.so.1"; 18 19 #[cfg(target_os = "android")] 20 const LIB_PATH: &str = "libvulkan.so"; 21 22 #[cfg(any(target_os = "macos", target_os = "ios"))] 23 const LIB_PATH: &str = "libvulkan.dylib"; 24 25 #[derive(Debug)] 26 pub enum LoadingError { 27 LibraryLoadFailure(libloading::Error), 28 MissingEntryPoint(MissingEntryPoint), 29 } 30 31 impl fmt::Display for LoadingError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 33 match self { 34 LoadingError::LibraryLoadFailure(err) => fmt::Display::fmt(err, f), 35 LoadingError::MissingEntryPoint(err) => fmt::Display::fmt(err, f), 36 } 37 } 38 } 39 40 impl Error for LoadingError { source(&self) -> Option<&(dyn Error + 'static)>41 fn source(&self) -> Option<&(dyn Error + 'static)> { 42 Some(match self { 43 LoadingError::LibraryLoadFailure(err) => err, 44 LoadingError::MissingEntryPoint(err) => err, 45 }) 46 } 47 } 48 49 impl From<MissingEntryPoint> for LoadingError { from(err: MissingEntryPoint) -> Self50 fn from(err: MissingEntryPoint) -> Self { 51 LoadingError::MissingEntryPoint(err) 52 } 53 } 54 55 /// Default function loader 56 pub type Entry = EntryCustom<Arc<Library>>; 57 58 impl Entry { 59 /// Load default Vulkan library for the current platform 60 /// 61 /// # Safety 62 /// `dlopen`ing native libraries is inherently unsafe. The safety guidelines 63 /// for [`Library::new`] and [`Library::get`] apply here. 64 /// 65 /// ```no_run 66 /// use ash::{vk, Entry}; 67 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 68 /// let entry = unsafe { Entry::new() }?; 69 /// let app_info = vk::ApplicationInfo { 70 /// api_version: vk::make_api_version(0, 1, 0, 0), 71 /// ..Default::default() 72 /// }; 73 /// let create_info = vk::InstanceCreateInfo { 74 /// p_application_info: &app_info, 75 /// ..Default::default() 76 /// }; 77 /// let instance = unsafe { entry.create_instance(&create_info, None)? }; 78 /// # Ok(()) } 79 /// ``` new() -> Result<Entry, LoadingError>80 pub unsafe fn new() -> Result<Entry, LoadingError> { 81 Self::with_library(LIB_PATH) 82 } 83 84 /// Load Vulkan library at `path` 85 /// 86 /// # Safety 87 /// `dlopen`ing native libraries is inherently unsafe. The safety guidelines 88 /// for [`Library::new`] and [`Library::get`] apply here. with_library(path: impl AsRef<OsStr>) -> Result<Entry, LoadingError>89 pub unsafe fn with_library(path: impl AsRef<OsStr>) -> Result<Entry, LoadingError> { 90 let lib = Library::new(path) 91 .map_err(LoadingError::LibraryLoadFailure) 92 .map(Arc::new)?; 93 94 Ok(Self::new_custom(lib, |vk_lib, name| { 95 vk_lib 96 .get(name.to_bytes_with_nul()) 97 .map(|symbol| *symbol) 98 .unwrap_or(ptr::null_mut()) 99 })?) 100 } 101 } 102