Support linking Vulkan directly (#457)
* Mark EntryCustom::new_custom as unsafe Passing a badly-behaved `load` function can invoke undefined behavior. * Document required feature for Entry * Support linking Vulkan directly This is the preferred pattern in most environments when an application cannot function without Vulkan, as it saves the libloading dependency, eliminates an error case, and makes the Vulkan dependency visible to the OS. * Rename libloading feature to "loaded" * Link by default * Guide users towards linking the loader directly * Remove unnecessary error type InstanceError::LoadError was never constructed. * Unify entry types Simplifies the interface and allows a bunch of code to become monomorphic.
This commit is contained in:
parent
1b4c82e1d6
commit
aa7b429f4f
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: check
|
command: check
|
||||||
args: --workspace --all-targets
|
args: --workspace --all-targets --all-features
|
||||||
|
|
||||||
generated:
|
generated:
|
||||||
name: Generated
|
name: Generated
|
||||||
|
@ -47,6 +47,8 @@ jobs:
|
||||||
name: Test Suite
|
name: Test Suite
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: Install Vulkan loader
|
||||||
|
run: sudo apt-get install libvulkan-dev
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -219,6 +219,11 @@ pub fn create_command_pool(&self,
|
||||||
let pool = device.create_command_pool(&pool_create_info).unwrap();
|
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
|
## Example
|
||||||
You can find the examples [here](https://github.com/MaikKlein/ash/tree/master/examples).
|
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/)
|
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/)
|
||||||
|
|
|
@ -15,7 +15,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
.build(&events_loop)?;
|
.build(&events_loop)?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let entry = ash::Entry::new()?;
|
let entry = ash::Entry::new();
|
||||||
let surface_extensions = ash_window::enumerate_required_extensions(&window)?;
|
let surface_extensions = ash_window::enumerate_required_extensions(&window)?;
|
||||||
let instance_extensions = surface_extensions
|
let instance_extensions = surface_extensions
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -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 raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
||||||
use std::ffi::CStr;
|
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
|
/// 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
|
/// usage, the [`Instance`] this was called on must be dropped later than the
|
||||||
/// resulting [`vk::SurfaceKHR`].
|
/// resulting [`vk::SurfaceKHR`].
|
||||||
pub unsafe fn create_surface<L>(
|
pub unsafe fn create_surface(
|
||||||
entry: &EntryCustom<L>,
|
entry: &Entry,
|
||||||
instance: &Instance,
|
instance: &Instance,
|
||||||
window_handle: &dyn HasRawWindowHandle,
|
window_handle: &dyn HasRawWindowHandle,
|
||||||
allocation_callbacks: Option<&vk::AllocationCallbacks>,
|
allocation_callbacks: Option<&vk::AllocationCallbacks>,
|
||||||
|
|
|
@ -14,7 +14,15 @@ edition = "2018"
|
||||||
libloading = { version = "0.7", optional = true }
|
libloading = { version = "0.7", optional = true }
|
||||||
|
|
||||||
[features]
|
[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]
|
[package.metadata.release]
|
||||||
no-dev-version = true
|
no-dev-version = true
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
all-features = true
|
||||||
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
24
ash/build.rs
Normal file
24
ash/build.rs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
219
ash/src/entry.rs
219
ash/src/entry.rs
|
@ -2,41 +2,137 @@ use crate::instance::Instance;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use std::error::Error;
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
#[cfg(feature = "loaded")]
|
||||||
|
use std::ffi::OsStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::ptr;
|
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),
|
#[cfg(feature = "loaded")]
|
||||||
/// the [`vkGetInstanceProcAddr`][vk::StaticFn::get_instance_proc_addr()] loader function from
|
use libloading::Library;
|
||||||
/// this library (in [`vk::StaticFn`]), and Vulkan's "entry point" functions (resolved with `NULL`
|
|
||||||
/// `instance`) as listed in [`vkGetInstanceProcAddr`'s description].
|
/// Holds the Vulkan functions independent of a particular instance
|
||||||
///
|
|
||||||
/// [`vkGetInstanceProcAddr`'s description]: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetInstanceProcAddr.html#_description
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EntryCustom<L> {
|
pub struct Entry {
|
||||||
static_fn: vk::StaticFn,
|
static_fn: vk::StaticFn,
|
||||||
entry_fn_1_0: vk::EntryFnV1_0,
|
entry_fn_1_0: vk::EntryFnV1_0,
|
||||||
entry_fn_1_1: vk::EntryFnV1_1,
|
entry_fn_1_1: vk::EntryFnV1_1,
|
||||||
entry_fn_1_2: vk::EntryFnV1_2,
|
entry_fn_1_2: vk::EntryFnV1_2,
|
||||||
lib: L,
|
#[cfg(feature = "loaded")]
|
||||||
|
_lib_guard: Option<Arc<Library>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vulkan core 1.0
|
/// Vulkan core 1.0
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
impl<L> EntryCustom<L> {
|
impl Entry {
|
||||||
pub fn new_custom<Load>(
|
/// Load entry points from a Vulkan loader linked at compile time
|
||||||
mut lib: L,
|
///
|
||||||
mut load: Load,
|
/// Note that instance/device functions are still fetched via `vkGetInstanceProcAddr` and
|
||||||
) -> std::result::Result<Self, MissingEntryPoint>
|
/// `vkGetDeviceProcAddr` for maximum performance.
|
||||||
where
|
///
|
||||||
Load: FnMut(&mut L, &::std::ffi::CStr) -> *const c_void,
|
/// ```no_run
|
||||||
{
|
/// use ash::{vk, Entry};
|
||||||
// Bypass the normal StaticFn::load so we can return an error
|
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let static_fn = vk::StaticFn::load_checked(|name| load(&mut lib, name))?;
|
/// 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<dyn std::error::Error>> {
|
||||||
|
/// 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<Self, LoadingError> {
|
||||||
|
#[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<OsStr>) -> Result<Self, LoadingError> {
|
||||||
|
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 {
|
let load_fn = |name: &std::ffi::CStr| unsafe {
|
||||||
mem::transmute(static_fn.get_instance_proc_addr(vk::Instance::null(), name.as_ptr()))
|
mem::transmute(static_fn.get_instance_proc_addr(vk::Instance::null(), name.as_ptr()))
|
||||||
};
|
};
|
||||||
|
@ -44,13 +140,14 @@ impl<L> EntryCustom<L> {
|
||||||
let entry_fn_1_1 = vk::EntryFnV1_1::load(load_fn);
|
let entry_fn_1_1 = vk::EntryFnV1_1::load(load_fn);
|
||||||
let entry_fn_1_2 = vk::EntryFnV1_2::load(load_fn);
|
let entry_fn_1_2 = vk::EntryFnV1_2::load(load_fn);
|
||||||
|
|
||||||
Ok(EntryCustom {
|
Self {
|
||||||
static_fn,
|
static_fn,
|
||||||
entry_fn_1_0,
|
entry_fn_1_0,
|
||||||
entry_fn_1_1,
|
entry_fn_1_1,
|
||||||
entry_fn_1_2,
|
entry_fn_1_2,
|
||||||
lib,
|
#[cfg(feature = "loaded")]
|
||||||
})
|
_lib_guard: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fp_v1_0(&self) -> &vk::EntryFnV1_0 {
|
pub fn fp_v1_0(&self) -> &vk::EntryFnV1_0 {
|
||||||
|
@ -65,7 +162,7 @@ impl<L> EntryCustom<L> {
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use ash::{Entry, vk};
|
/// # use ash::{Entry, vk};
|
||||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
/// let entry = unsafe { Entry::new() }?;
|
/// let entry = Entry::new();
|
||||||
/// match entry.try_enumerate_instance_version()? {
|
/// match entry.try_enumerate_instance_version()? {
|
||||||
/// // Vulkan 1.1+
|
/// // Vulkan 1.1+
|
||||||
/// Some(version) => {
|
/// Some(version) => {
|
||||||
|
@ -107,7 +204,7 @@ impl<L> EntryCustom<L> {
|
||||||
&self,
|
&self,
|
||||||
create_info: &vk::InstanceCreateInfo,
|
create_info: &vk::InstanceCreateInfo,
|
||||||
allocation_callbacks: Option<&vk::AllocationCallbacks>,
|
allocation_callbacks: Option<&vk::AllocationCallbacks>,
|
||||||
) -> Result<Instance, InstanceError> {
|
) -> VkResult<Instance> {
|
||||||
let mut instance = mem::zeroed();
|
let mut instance = mem::zeroed();
|
||||||
self.entry_fn_1_0
|
self.entry_fn_1_0
|
||||||
.create_instance(
|
.create_instance(
|
||||||
|
@ -115,8 +212,7 @@ impl<L> EntryCustom<L> {
|
||||||
allocation_callbacks.as_raw_ptr(),
|
allocation_callbacks.as_raw_ptr(),
|
||||||
&mut instance,
|
&mut instance,
|
||||||
)
|
)
|
||||||
.result()
|
.result()?;
|
||||||
.map_err(InstanceError::VkError)?;
|
|
||||||
Ok(Instance::load(&self.static_fn, instance))
|
Ok(Instance::load(&self.static_fn, instance))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +250,7 @@ impl<L> EntryCustom<L> {
|
||||||
|
|
||||||
/// Vulkan core 1.1
|
/// Vulkan core 1.1
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
impl<L> EntryCustom<L> {
|
impl Entry {
|
||||||
pub fn fp_v1_1(&self) -> &vk::EntryFnV1_1 {
|
pub fn fp_v1_1(&self) -> &vk::EntryFnV1_1 {
|
||||||
&self.entry_fn_1_1
|
&self.entry_fn_1_1
|
||||||
}
|
}
|
||||||
|
@ -175,29 +271,19 @@ impl<L> EntryCustom<L> {
|
||||||
|
|
||||||
/// Vulkan core 1.2
|
/// Vulkan core 1.2
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
impl<L> EntryCustom<L> {
|
impl Entry {
|
||||||
pub fn fp_v1_2(&self) -> &vk::EntryFnV1_2 {
|
pub fn fp_v1_2(&self) -> &vk::EntryFnV1_2 {
|
||||||
&self.entry_fn_1_2
|
&self.entry_fn_1_2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[cfg(feature = "linked")]
|
||||||
pub enum InstanceError {
|
impl Default for Entry {
|
||||||
LoadError(Vec<&'static str>),
|
fn default() -> Self {
|
||||||
VkError(vk::Result),
|
Self::new()
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for InstanceError {}
|
|
||||||
|
|
||||||
impl vk::StaticFn {
|
impl vk::StaticFn {
|
||||||
pub fn load_checked<F>(mut _f: F) -> Result<Self, MissingEntryPoint>
|
pub fn load_checked<F>(mut _f: F) -> Result<Self, MissingEntryPoint>
|
||||||
where
|
where
|
||||||
|
@ -228,3 +314,50 @@ impl std::fmt::Display for MissingEntryPoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::error::Error 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<MissingEntryPoint> for LoadingError {
|
||||||
|
fn from(err: MissingEntryPoint) -> Self {
|
||||||
|
LoadingError::MissingEntryPoint(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(feature = "loaded")]
|
||||||
|
pub use self::loaded::*;
|
||||||
|
|
|
@ -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<MissingEntryPoint> for LoadingError {
|
|
||||||
fn from(err: MissingEntryPoint) -> Self {
|
|
||||||
LoadingError::MissingEntryPoint(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Default function loader
|
|
||||||
pub type Entry = EntryCustom<Arc<Library>>;
|
|
||||||
|
|
||||||
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<dyn std::error::Error>> {
|
|
||||||
/// 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<Entry, LoadingError> {
|
|
||||||
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<OsStr>) -> Result<Entry, LoadingError> {
|
|
||||||
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())
|
|
||||||
})?)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct DebugReport {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugReport {
|
impl DebugReport {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let debug_report_fn = vk::ExtDebugReportFn::load(|name| unsafe {
|
let debug_report_fn = vk::ExtDebugReportFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{vk, RawPtr};
|
use crate::{vk, RawPtr};
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ pub struct DebugUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugUtils {
|
impl DebugUtils {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let debug_utils_fn = vk::ExtDebugUtilsFn::load(|name| unsafe {
|
let debug_utils_fn = vk::ExtDebugUtilsFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct MetalSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetalSurface {
|
impl MetalSurface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::ExtMetalSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::ExtMetalSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ pub struct ToolingInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolingInfo {
|
impl ToolingInfo {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let tooling_info_fn = vk::ExtToolingInfoFn::load(|name| unsafe {
|
let tooling_info_fn = vk::ExtToolingInfoFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct AndroidSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AndroidSurface {
|
impl AndroidSurface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::KhrAndroidSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::KhrAndroidSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct Display {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let display_fn = vk::KhrDisplayFn::load(|name| unsafe {
|
let display_fn = vk::KhrDisplayFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -12,7 +12,7 @@ pub struct GetPhysicalDeviceProperties2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetPhysicalDeviceProperties2 {
|
impl GetPhysicalDeviceProperties2 {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let get_physical_device_properties2_fn =
|
let get_physical_device_properties2_fn =
|
||||||
vk::KhrGetPhysicalDeviceProperties2Fn::load(|name| unsafe {
|
vk::KhrGetPhysicalDeviceProperties2Fn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ pub struct PipelineExecutableProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PipelineExecutableProperties {
|
impl PipelineExecutableProperties {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let pipeline_executable_properties_fn =
|
let pipeline_executable_properties_fn =
|
||||||
vk::KhrPipelineExecutablePropertiesFn::load(|name| unsafe {
|
vk::KhrPipelineExecutablePropertiesFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct Surface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Surface {
|
impl Surface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::KhrSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::KhrSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ pub struct TimelineSemaphore {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimelineSemaphore {
|
impl TimelineSemaphore {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let timeline_semaphore_fn = vk::KhrTimelineSemaphoreFn::load(|name| unsafe {
|
let timeline_semaphore_fn = vk::KhrTimelineSemaphoreFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct WaylandSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WaylandSurface {
|
impl WaylandSurface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::KhrWaylandSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::KhrWaylandSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct Win32Surface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Win32Surface {
|
impl Win32Surface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::KhrWin32SurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::KhrWin32SurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct XcbSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XcbSurface {
|
impl XcbSurface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::KhrXcbSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::KhrXcbSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct XlibSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XlibSurface {
|
impl XlibSurface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::KhrXlibSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::KhrXlibSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct IOSSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IOSSurface {
|
impl IOSSurface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::MvkIosSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::MvkIosSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct MacOSSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacOSSurface {
|
impl MacOSSurface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::MvkMacosSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::MvkMacosSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
use crate::{EntryCustom, Instance};
|
use crate::{Entry, Instance};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct ViSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ViSurface {
|
impl ViSurface {
|
||||||
pub fn new<L>(entry: &EntryCustom<L>, instance: &Instance) -> Self {
|
pub fn new(entry: &Entry, instance: &Instance) -> Self {
|
||||||
let surface_fn = vk::NnViSurfaceFn::load(|name| unsafe {
|
let surface_fn = vk::NnViSurfaceFn::load(|name| unsafe {
|
||||||
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
mem::transmute(entry.get_instance_proc_addr(instance.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
clippy::missing_safety_doc,
|
clippy::missing_safety_doc,
|
||||||
clippy::upper_case_acronyms
|
clippy::upper_case_acronyms
|
||||||
)]
|
)]
|
||||||
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
//! # Vulkan API
|
//! # Vulkan API
|
||||||
//!
|
//!
|
||||||
//! <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/index.html>
|
//! <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/index.html>
|
||||||
|
@ -12,7 +13,7 @@
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use ash::{vk, Entry};
|
//! use ash::{vk, Entry};
|
||||||
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
//! let entry = unsafe { Entry::new() }?;
|
//! let entry = Entry::new();
|
||||||
//! let app_info = vk::ApplicationInfo {
|
//! let app_info = vk::ApplicationInfo {
|
||||||
//! api_version: vk::make_api_version(0, 1, 0, 0),
|
//! api_version: vk::make_api_version(0, 1, 0, 0),
|
||||||
//! ..Default::default()
|
//! ..Default::default()
|
||||||
|
@ -26,22 +27,19 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Getting started
|
//! ## 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()].
|
//! Load the Vulkan library linked at compile time using [`Entry::new()`], or load it at runtime
|
||||||
//! These loaders use [`libloading`]. If you wish to perform function loading yourself
|
//! using [`Entry::load()`], which uses `libloading`. If you want to perform entry point loading
|
||||||
//! call [`EntryCustom::new_custom()`] with a closure turning function names
|
//! yourself, call [`Entry::from_static_fn()`].
|
||||||
//! into function pointers.
|
|
||||||
|
|
||||||
pub use crate::device::Device;
|
pub use crate::device::Device;
|
||||||
pub use crate::entry::{EntryCustom, InstanceError};
|
pub use crate::entry::Entry;
|
||||||
#[cfg(feature = "libloading")]
|
#[cfg(feature = "loaded")]
|
||||||
pub use crate::entry_libloading::{Entry, LoadingError};
|
pub use crate::entry::LoadingError;
|
||||||
pub use crate::instance::Instance;
|
pub use crate::instance::Instance;
|
||||||
|
|
||||||
mod device;
|
mod device;
|
||||||
mod entry;
|
mod entry;
|
||||||
#[cfg(feature = "libloading")]
|
|
||||||
mod entry_libloading;
|
|
||||||
mod instance;
|
mod instance;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use ash::extensions::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use ash::{vk, Entry};
|
use ash::{vk, Entry};
|
||||||
pub use ash::{Device, EntryCustom, Instance};
|
pub use ash::{Device, Instance};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
@ -204,7 +204,7 @@ impl ExampleBase {
|
||||||
))
|
))
|
||||||
.build(&events_loop)
|
.build(&events_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let entry = Entry::new().unwrap();
|
let entry = Entry::new();
|
||||||
let app_name = CString::new("VulkanTriangle").unwrap();
|
let app_name = CString::new("VulkanTriangle").unwrap();
|
||||||
|
|
||||||
let layer_names = [CString::new("VK_LAYER_KHRONOS_validation").unwrap()];
|
let layer_names = [CString::new("VK_LAYER_KHRONOS_validation").unwrap()];
|
||||||
|
|
Loading…
Reference in a new issue