diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33bde8e..646d4b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - uses: actions-rs/cargo@v1 with: command: check - args: --workspace --all-targets + args: --workspace --all-targets --all-features generated: name: Generated @@ -47,6 +47,8 @@ jobs: name: Test Suite runs-on: ubuntu-latest steps: + - name: Install Vulkan loader + run: sudo apt-get install libvulkan-dev - uses: actions/checkout@v1 - uses: actions-rs/toolchain@v1 with: diff --git a/README.md b/README.md index 24397ad..9bef027 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,11 @@ pub fn create_command_pool(&self, let pool = device.create_command_pool(&pool_create_info).unwrap(); ``` +### Optional linking + +The default `linked` cargo feature will link your binary with the Vulkan loader directly and expose the infallible `Entry::new`. +If your application can handle Vulkan being missing at runtime, you can instead enable the `loaded` feature to dynamically load Vulkan with `Entry::load`. + ## Example You can find the examples [here](https://github.com/MaikKlein/ash/tree/master/examples). All examples currently require: the LunarG Validation layers and a Vulkan library that is visible in your `PATH`. An easy way to get started is to use the [LunarG Vulkan SDK](https://lunarg.com/vulkan-sdk/) diff --git a/ash-window/examples/winit.rs b/ash-window/examples/winit.rs index 9158f39..0921897 100644 --- a/ash-window/examples/winit.rs +++ b/ash-window/examples/winit.rs @@ -15,7 +15,7 @@ fn main() -> Result<(), Box> { .build(&events_loop)?; unsafe { - let entry = ash::Entry::new()?; + let entry = ash::Entry::new(); let surface_extensions = ash_window::enumerate_required_extensions(&window)?; let instance_extensions = surface_extensions .iter() diff --git a/ash-window/src/lib.rs b/ash-window/src/lib.rs index 83fc84f..1c74435 100644 --- a/ash-window/src/lib.rs +++ b/ash-window/src/lib.rs @@ -1,4 +1,4 @@ -use ash::{extensions::khr, prelude::*, vk, EntryCustom, Instance}; +use ash::{extensions::khr, prelude::*, vk, Entry, Instance}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use std::ffi::CStr; @@ -14,8 +14,8 @@ use ash::extensions::ext; // portability extensions /// In order for the created [`vk::SurfaceKHR`] to be valid for the duration of its /// usage, the [`Instance`] this was called on must be dropped later than the /// resulting [`vk::SurfaceKHR`]. -pub unsafe fn create_surface( - entry: &EntryCustom, +pub unsafe fn create_surface( + entry: &Entry, instance: &Instance, window_handle: &dyn HasRawWindowHandle, allocation_callbacks: Option<&vk::AllocationCallbacks>, diff --git a/ash/Cargo.toml b/ash/Cargo.toml index 914f217..bda7aa8 100644 --- a/ash/Cargo.toml +++ b/ash/Cargo.toml @@ -14,7 +14,15 @@ edition = "2018" libloading = { version = "0.7", optional = true } [features] -default = ["libloading"] +default = ["linked"] +# Link the Vulkan loader at compile time. +linked = [] +# Support searching for the Vulkan loader manually at runtime. +loaded = ["libloading"] [package.metadata.release] no-dev-version = true + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/ash/build.rs b/ash/build.rs new file mode 100644 index 0000000..ba6e61d --- /dev/null +++ b/ash/build.rs @@ -0,0 +1,24 @@ +fn main() { + #[cfg(feature = "linked")] + { + use std::env; + + let target_family = env::var("CARGO_CFG_TARGET_FAMILY").unwrap(); + let target_pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap(); + + println!("cargo:rerun-if-env-changed=VULKAN_SDK"); + if let Ok(var) = env::var("VULKAN_SDK") { + let suffix = match (&*target_family, &*target_pointer_width) { + ("windows", "32") => "Lib32", + ("windows", "64") => "Lib", + _ => "lib", + }; + println!("cargo:rustc-link-search={}/{}", var, suffix); + } + let lib = match &*target_family { + "windows" => "vulkan-1", + _ => "vulkan", + }; + println!("cargo:rustc-link-lib={}", lib); + } +} diff --git a/ash/src/entry.rs b/ash/src/entry.rs index 280076b..f6f91dd 100644 --- a/ash/src/entry.rs +++ b/ash/src/entry.rs @@ -2,41 +2,137 @@ use crate::instance::Instance; use crate::prelude::*; use crate::vk; use crate::RawPtr; -use std::error::Error; use std::ffi::CStr; -use std::fmt; +#[cfg(feature = "loaded")] +use std::ffi::OsStr; use std::mem; use std::os::raw::c_char; use std::os::raw::c_void; use std::ptr; +#[cfg(feature = "loaded")] +use std::sync::Arc; -/// Holds a custom type `L` to load symbols from (usually a handle to a `dlopen`ed library), -/// the [`vkGetInstanceProcAddr`][vk::StaticFn::get_instance_proc_addr()] loader function from -/// this library (in [`vk::StaticFn`]), and Vulkan's "entry point" functions (resolved with `NULL` -/// `instance`) as listed in [`vkGetInstanceProcAddr`'s description]. -/// -/// [`vkGetInstanceProcAddr`'s description]: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetInstanceProcAddr.html#_description +#[cfg(feature = "loaded")] +use libloading::Library; + +/// Holds the Vulkan functions independent of a particular instance #[derive(Clone)] -pub struct EntryCustom { +pub struct Entry { static_fn: vk::StaticFn, entry_fn_1_0: vk::EntryFnV1_0, entry_fn_1_1: vk::EntryFnV1_1, entry_fn_1_2: vk::EntryFnV1_2, - lib: L, + #[cfg(feature = "loaded")] + _lib_guard: Option>, } /// Vulkan core 1.0 #[allow(non_camel_case_types)] -impl EntryCustom { - pub fn new_custom( - mut lib: L, - mut load: Load, - ) -> std::result::Result - where - Load: FnMut(&mut L, &::std::ffi::CStr) -> *const c_void, - { - // Bypass the normal StaticFn::load so we can return an error - let static_fn = vk::StaticFn::load_checked(|name| load(&mut lib, name))?; +impl Entry { + /// Load entry points from a Vulkan loader linked at compile time + /// + /// Note that instance/device functions are still fetched via `vkGetInstanceProcAddr` and + /// `vkGetDeviceProcAddr` for maximum performance. + /// + /// ```no_run + /// use ash::{vk, Entry}; + /// # fn main() -> Result<(), Box> { + /// let entry = Entry::new(); + /// let app_info = vk::ApplicationInfo { + /// api_version: vk::make_api_version(0, 1, 0, 0), + /// ..Default::default() + /// }; + /// let create_info = vk::InstanceCreateInfo { + /// p_application_info: &app_info, + /// ..Default::default() + /// }; + /// let instance = unsafe { entry.create_instance(&create_info, None)? }; + /// # Ok(()) } + /// ``` + #[cfg(feature = "linked")] + #[cfg_attr(docsrs, doc(cfg(feature = "linked")))] + pub fn new() -> Self { + // Sound because we're linking to Vulkan, which provides a vkGetInstanceProcAddr that has + // defined behavior in this use. + unsafe { + Self::from_static_fn(vk::StaticFn { + get_instance_proc_addr: vkGetInstanceProcAddr, + }) + } + } + + /// Load default Vulkan library for the current platform + /// + /// # Safety + /// `dlopen`ing native libraries is inherently unsafe. The safety guidelines + /// for [`Library::new()`] and [`Library::get()`] apply here. + /// + /// ```no_run + /// use ash::{vk, Entry}; + /// # fn main() -> Result<(), Box> { + /// let entry = unsafe { Entry::load()? }; + /// let app_info = vk::ApplicationInfo { + /// api_version: vk::make_api_version(0, 1, 0, 0), + /// ..Default::default() + /// }; + /// let create_info = vk::InstanceCreateInfo { + /// p_application_info: &app_info, + /// ..Default::default() + /// }; + /// let instance = unsafe { entry.create_instance(&create_info, None)? }; + /// # Ok(()) } + /// ``` + #[cfg(feature = "loaded")] + #[cfg_attr(docsrs, doc(cfg(feature = "loaded")))] + pub unsafe fn load() -> Result { + #[cfg(windows)] + const LIB_PATH: &str = "vulkan-1.dll"; + + #[cfg(all( + unix, + not(any(target_os = "macos", target_os = "ios", target_os = "android")) + ))] + const LIB_PATH: &str = "libvulkan.so.1"; + + #[cfg(target_os = "android")] + const LIB_PATH: &str = "libvulkan.so"; + + #[cfg(any(target_os = "macos", target_os = "ios"))] + const LIB_PATH: &str = "libvulkan.dylib"; + + Self::load_from(LIB_PATH) + } + + /// Load Vulkan library at `path` + /// + /// # Safety + /// `dlopen`ing native libraries is inherently unsafe. The safety guidelines + /// for [`Library::new()`] and [`Library::get()`] apply here. + #[cfg(feature = "loaded")] + #[cfg_attr(docsrs, doc(cfg(feature = "loaded")))] + pub unsafe fn load_from(path: impl AsRef) -> Result { + let lib = Library::new(path) + .map_err(LoadingError::LibraryLoadFailure) + .map(Arc::new)?; + + let static_fn = vk::StaticFn::load_checked(|name| { + lib.get(name.to_bytes_with_nul()) + .map(|symbol| *symbol) + .unwrap_or(ptr::null_mut()) + })?; + + Ok(Self { + _lib_guard: Some(lib), + ..Self::from_static_fn(static_fn) + }) + } + + /// Load entry points based on an already-loaded [`vk::StaticFn`] + /// + /// # Safety + /// `static_fn` must contain valid function pointers that comply with the semantics specified by + /// Vulkan 1.0, which must remain valid for at least the lifetime of the returned [`Entry`]. + pub unsafe fn from_static_fn(static_fn: vk::StaticFn) -> Self { let load_fn = |name: &std::ffi::CStr| unsafe { mem::transmute(static_fn.get_instance_proc_addr(vk::Instance::null(), name.as_ptr())) }; @@ -44,13 +140,14 @@ impl EntryCustom { let entry_fn_1_1 = vk::EntryFnV1_1::load(load_fn); let entry_fn_1_2 = vk::EntryFnV1_2::load(load_fn); - Ok(EntryCustom { + Self { static_fn, entry_fn_1_0, entry_fn_1_1, entry_fn_1_2, - lib, - }) + #[cfg(feature = "loaded")] + _lib_guard: None, + } } pub fn fp_v1_0(&self) -> &vk::EntryFnV1_0 { @@ -65,7 +162,7 @@ impl EntryCustom { /// ```no_run /// # use ash::{Entry, vk}; /// # fn main() -> Result<(), Box> { - /// let entry = unsafe { Entry::new() }?; + /// let entry = Entry::new(); /// match entry.try_enumerate_instance_version()? { /// // Vulkan 1.1+ /// Some(version) => { @@ -107,7 +204,7 @@ impl EntryCustom { &self, create_info: &vk::InstanceCreateInfo, allocation_callbacks: Option<&vk::AllocationCallbacks>, - ) -> Result { + ) -> VkResult { let mut instance = mem::zeroed(); self.entry_fn_1_0 .create_instance( @@ -115,8 +212,7 @@ impl EntryCustom { allocation_callbacks.as_raw_ptr(), &mut instance, ) - .result() - .map_err(InstanceError::VkError)?; + .result()?; Ok(Instance::load(&self.static_fn, instance)) } @@ -154,7 +250,7 @@ impl EntryCustom { /// Vulkan core 1.1 #[allow(non_camel_case_types)] -impl EntryCustom { +impl Entry { pub fn fp_v1_1(&self) -> &vk::EntryFnV1_1 { &self.entry_fn_1_1 } @@ -175,29 +271,19 @@ impl EntryCustom { /// Vulkan core 1.2 #[allow(non_camel_case_types)] -impl EntryCustom { +impl Entry { pub fn fp_v1_2(&self) -> &vk::EntryFnV1_2 { &self.entry_fn_1_2 } } -#[derive(Clone, Debug)] -pub enum InstanceError { - LoadError(Vec<&'static str>), - VkError(vk::Result), -} - -impl fmt::Display for InstanceError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - InstanceError::LoadError(e) => write!(f, "{}", e.join("; ")), - InstanceError::VkError(e) => write!(f, "{}", e), - } +#[cfg(feature = "linked")] +impl Default for Entry { + fn default() -> Self { + Self::new() } } -impl Error for InstanceError {} - impl vk::StaticFn { pub fn load_checked(mut _f: F) -> Result where @@ -228,3 +314,50 @@ impl std::fmt::Display for MissingEntryPoint { } } impl std::error::Error for MissingEntryPoint {} + +#[cfg(feature = "linked")] +extern "system" { + fn vkGetInstanceProcAddr(instance: vk::Instance, name: *const c_char) + -> vk::PFN_vkVoidFunction; +} + +#[cfg(feature = "loaded")] +mod loaded { + use std::error::Error; + use std::fmt; + + use super::*; + + #[derive(Debug)] + #[cfg_attr(docsrs, doc(cfg(feature = "loaded")))] + pub enum LoadingError { + LibraryLoadFailure(libloading::Error), + MissingEntryPoint(MissingEntryPoint), + } + + impl fmt::Display for LoadingError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + LoadingError::LibraryLoadFailure(err) => fmt::Display::fmt(err, f), + LoadingError::MissingEntryPoint(err) => fmt::Display::fmt(err, f), + } + } + } + + impl Error for LoadingError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + Some(match self { + LoadingError::LibraryLoadFailure(err) => err, + LoadingError::MissingEntryPoint(err) => err, + }) + } + } + + impl From for LoadingError { + fn from(err: MissingEntryPoint) -> Self { + LoadingError::MissingEntryPoint(err) + } + } +} +#[cfg(feature = "loaded")] +pub use self::loaded::*; diff --git a/ash/src/entry_libloading.rs b/ash/src/entry_libloading.rs deleted file mode 100644 index 3e9386a..0000000 --- a/ash/src/entry_libloading.rs +++ /dev/null @@ -1,101 +0,0 @@ -use crate::entry::EntryCustom; -use crate::entry::MissingEntryPoint; -use libloading::Library; -use std::error::Error; -use std::ffi::OsStr; -use std::fmt; -use std::ptr; -use std::sync::Arc; - -#[cfg(windows)] -const LIB_PATH: &str = "vulkan-1.dll"; - -#[cfg(all( - unix, - not(any(target_os = "macos", target_os = "ios", target_os = "android")) -))] -const LIB_PATH: &str = "libvulkan.so.1"; - -#[cfg(target_os = "android")] -const LIB_PATH: &str = "libvulkan.so"; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -const LIB_PATH: &str = "libvulkan.dylib"; - -#[derive(Debug)] -pub enum LoadingError { - LibraryLoadFailure(libloading::Error), - MissingEntryPoint(MissingEntryPoint), -} - -impl fmt::Display for LoadingError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - LoadingError::LibraryLoadFailure(err) => fmt::Display::fmt(err, f), - LoadingError::MissingEntryPoint(err) => fmt::Display::fmt(err, f), - } - } -} - -impl Error for LoadingError { - fn source(&self) -> Option<&(dyn Error + 'static)> { - Some(match self { - LoadingError::LibraryLoadFailure(err) => err, - LoadingError::MissingEntryPoint(err) => err, - }) - } -} - -impl From for LoadingError { - fn from(err: MissingEntryPoint) -> Self { - LoadingError::MissingEntryPoint(err) - } -} - -/// Default function loader -pub type Entry = EntryCustom>; - -impl Entry { - /// Load default Vulkan library for the current platform - /// - /// # Safety - /// `dlopen`ing native libraries is inherently unsafe. The safety guidelines - /// for [`Library::new`] and [`Library::get`] apply here. - /// - /// ```no_run - /// use ash::{vk, Entry}; - /// # fn main() -> Result<(), Box> { - /// let entry = unsafe { Entry::new() }?; - /// let app_info = vk::ApplicationInfo { - /// api_version: vk::make_api_version(0, 1, 0, 0), - /// ..Default::default() - /// }; - /// let create_info = vk::InstanceCreateInfo { - /// p_application_info: &app_info, - /// ..Default::default() - /// }; - /// let instance = unsafe { entry.create_instance(&create_info, None)? }; - /// # Ok(()) } - /// ``` - pub unsafe fn new() -> Result { - Self::with_library(LIB_PATH) - } - - /// Load Vulkan library at `path` - /// - /// # Safety - /// `dlopen`ing native libraries is inherently unsafe. The safety guidelines - /// for [`Library::new`] and [`Library::get`] apply here. - pub unsafe fn with_library(path: impl AsRef) -> Result { - let lib = Library::new(path) - .map_err(LoadingError::LibraryLoadFailure) - .map(Arc::new)?; - - Ok(Self::new_custom(lib, |vk_lib, name| { - vk_lib - .get(name.to_bytes_with_nul()) - .map(|symbol| *symbol) - .unwrap_or(ptr::null_mut()) - })?) - } -} diff --git a/ash/src/extensions/ext/debug_report.rs b/ash/src/extensions/ext/debug_report.rs index 3400566..89abb9b 100755 --- a/ash/src/extensions/ext/debug_report.rs +++ b/ash/src/extensions/ext/debug_report.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct DebugReport { } impl DebugReport { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let debug_report_fn = vk::ExtDebugReportFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/ext/debug_utils.rs b/ash/src/extensions/ext/debug_utils.rs index 69ce2e9..9faa401 100755 --- a/ash/src/extensions/ext/debug_utils.rs +++ b/ash/src/extensions/ext/debug_utils.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::{vk, RawPtr}; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -11,7 +11,7 @@ pub struct DebugUtils { } impl DebugUtils { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let debug_utils_fn = vk::ExtDebugUtilsFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/ext/metal_surface.rs b/ash/src/extensions/ext/metal_surface.rs index c76d436..6cf3207 100644 --- a/ash/src/extensions/ext/metal_surface.rs +++ b/ash/src/extensions/ext/metal_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct MetalSurface { } impl MetalSurface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::ExtMetalSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/ext/tooling_info.rs b/ash/src/extensions/ext/tooling_info.rs index 284a472..0b0c8ae 100644 --- a/ash/src/extensions/ext/tooling_info.rs +++ b/ash/src/extensions/ext/tooling_info.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::vk; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -11,7 +11,7 @@ pub struct ToolingInfo { } impl ToolingInfo { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let tooling_info_fn = vk::ExtToolingInfoFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/khr/android_surface.rs b/ash/src/extensions/khr/android_surface.rs index fef6b7d..354279e 100755 --- a/ash/src/extensions/khr/android_surface.rs +++ b/ash/src/extensions/khr/android_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct AndroidSurface { } impl AndroidSurface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::KhrAndroidSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/khr/display.rs b/ash/src/extensions/khr/display.rs index 4ae8a34..b24d597 100755 --- a/ash/src/extensions/khr/display.rs +++ b/ash/src/extensions/khr/display.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct Display { } impl Display { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let display_fn = vk::KhrDisplayFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/khr/get_physical_device_properties2.rs b/ash/src/extensions/khr/get_physical_device_properties2.rs index 57609fa..abf2331 100644 --- a/ash/src/extensions/khr/get_physical_device_properties2.rs +++ b/ash/src/extensions/khr/get_physical_device_properties2.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::vk; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; use std::ptr; @@ -12,7 +12,7 @@ pub struct GetPhysicalDeviceProperties2 { } impl GetPhysicalDeviceProperties2 { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let get_physical_device_properties2_fn = vk::KhrGetPhysicalDeviceProperties2Fn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) diff --git a/ash/src/extensions/khr/pipeline_executable_properties.rs b/ash/src/extensions/khr/pipeline_executable_properties.rs index fd85a76..3662f6f 100644 --- a/ash/src/extensions/khr/pipeline_executable_properties.rs +++ b/ash/src/extensions/khr/pipeline_executable_properties.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::vk; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -11,7 +11,7 @@ pub struct PipelineExecutableProperties { } impl PipelineExecutableProperties { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let pipeline_executable_properties_fn = vk::KhrPipelineExecutablePropertiesFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) diff --git a/ash/src/extensions/khr/surface.rs b/ash/src/extensions/khr/surface.rs index 3c19d22..d5607cd 100755 --- a/ash/src/extensions/khr/surface.rs +++ b/ash/src/extensions/khr/surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct Surface { } impl Surface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::KhrSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/khr/timeline_semaphore.rs b/ash/src/extensions/khr/timeline_semaphore.rs index fca074e..2abb7a2 100644 --- a/ash/src/extensions/khr/timeline_semaphore.rs +++ b/ash/src/extensions/khr/timeline_semaphore.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::vk; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -11,7 +11,7 @@ pub struct TimelineSemaphore { } impl TimelineSemaphore { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let timeline_semaphore_fn = vk::KhrTimelineSemaphoreFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/khr/wayland_surface.rs b/ash/src/extensions/khr/wayland_surface.rs index d4983df..241cdea 100755 --- a/ash/src/extensions/khr/wayland_surface.rs +++ b/ash/src/extensions/khr/wayland_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct WaylandSurface { } impl WaylandSurface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::KhrWaylandSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/khr/win32_surface.rs b/ash/src/extensions/khr/win32_surface.rs index d037fba..aef2d44 100755 --- a/ash/src/extensions/khr/win32_surface.rs +++ b/ash/src/extensions/khr/win32_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct Win32Surface { } impl Win32Surface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::KhrWin32SurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/khr/xcb_surface.rs b/ash/src/extensions/khr/xcb_surface.rs index c01d2f3..e538ce6 100755 --- a/ash/src/extensions/khr/xcb_surface.rs +++ b/ash/src/extensions/khr/xcb_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct XcbSurface { } impl XcbSurface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::KhrXcbSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/khr/xlib_surface.rs b/ash/src/extensions/khr/xlib_surface.rs index 0f53c39..5b0de68 100755 --- a/ash/src/extensions/khr/xlib_surface.rs +++ b/ash/src/extensions/khr/xlib_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct XlibSurface { } impl XlibSurface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::KhrXlibSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/mvk/ios_surface.rs b/ash/src/extensions/mvk/ios_surface.rs index a8491f2..3b12f3a 100755 --- a/ash/src/extensions/mvk/ios_surface.rs +++ b/ash/src/extensions/mvk/ios_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct IOSSurface { } impl IOSSurface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::MvkIosSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/mvk/macos_surface.rs b/ash/src/extensions/mvk/macos_surface.rs index 31ca0de..b20e3bb 100755 --- a/ash/src/extensions/mvk/macos_surface.rs +++ b/ash/src/extensions/mvk/macos_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct MacOSSurface { } impl MacOSSurface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::MvkMacosSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/extensions/nn/vi_surface.rs b/ash/src/extensions/nn/vi_surface.rs index e3ade6f..8634d12 100644 --- a/ash/src/extensions/nn/vi_surface.rs +++ b/ash/src/extensions/nn/vi_surface.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::vk; use crate::RawPtr; -use crate::{EntryCustom, Instance}; +use crate::{Entry, Instance}; use std::ffi::CStr; use std::mem; @@ -12,7 +12,7 @@ pub struct ViSurface { } impl ViSurface { - pub fn new(entry: &EntryCustom, instance: &Instance) -> Self { + pub fn new(entry: &Entry, instance: &Instance) -> Self { let surface_fn = vk::NnViSurfaceFn::load(|name| unsafe { mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr())) }); diff --git a/ash/src/lib.rs b/ash/src/lib.rs index c6ca4eb..af1b97e 100644 --- a/ash/src/lib.rs +++ b/ash/src/lib.rs @@ -3,6 +3,7 @@ clippy::missing_safety_doc, clippy::upper_case_acronyms )] +#![cfg_attr(docsrs, feature(doc_cfg))] //! # Vulkan API //! //! @@ -12,7 +13,7 @@ //! ```no_run //! use ash::{vk, Entry}; //! # fn main() -> Result<(), Box> { -//! let entry = unsafe { Entry::new() }?; +//! let entry = Entry::new(); //! let app_info = vk::ApplicationInfo { //! api_version: vk::make_api_version(0, 1, 0, 0), //! ..Default::default() @@ -26,22 +27,19 @@ //! ``` //! //! ## Getting started -//! Load the Vulkan library at the default location using [`Entry::new()`][EntryCustom<_>::new()], -//! or at a custom location using [`Entry::with_library("path/to/vulkan")`][EntryCustom<_>::with_library()]. -//! These loaders use [`libloading`]. If you wish to perform function loading yourself -//! call [`EntryCustom::new_custom()`] with a closure turning function names -//! into function pointers. +//! +//! Load the Vulkan library linked at compile time using [`Entry::new()`], or load it at runtime +//! using [`Entry::load()`], which uses `libloading`. If you want to perform entry point loading +//! yourself, call [`Entry::from_static_fn()`]. pub use crate::device::Device; -pub use crate::entry::{EntryCustom, InstanceError}; -#[cfg(feature = "libloading")] -pub use crate::entry_libloading::{Entry, LoadingError}; +pub use crate::entry::Entry; +#[cfg(feature = "loaded")] +pub use crate::entry::LoadingError; pub use crate::instance::Instance; mod device; mod entry; -#[cfg(feature = "libloading")] -mod entry_libloading; mod instance; pub mod prelude; pub mod util; diff --git a/examples/src/lib.rs b/examples/src/lib.rs index b37b75c..1c37f8b 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -7,7 +7,7 @@ use ash::extensions::{ }; use ash::{vk, Entry}; -pub use ash::{Device, EntryCustom, Instance}; +pub use ash::{Device, Instance}; use std::borrow::Cow; use std::cell::RefCell; use std::default::Default; @@ -204,7 +204,7 @@ impl ExampleBase { )) .build(&events_loop) .unwrap(); - let entry = Entry::new().unwrap(); + let entry = Entry::new(); let app_name = CString::new("VulkanTriangle").unwrap(); let layer_names = [CString::new("VK_LAYER_KHRONOS_validation").unwrap()];