Skip to content

Commit

Permalink
Support linking Vulkan directly
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Ralith committed Jul 30, 2021
1 parent c6466a9 commit 33c291b
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ pub fn create_command_pool(&self,
let pool = device.create_command_pool(&pool_create_info).unwrap();
```

### Optional linking

Enable the `linked` cargo feature to link your binary with the Vulkan loader directly and expose the infallible `EntryLinked`.
If your application can handle Vulkan being missing at runtime, you can instead use the default `libloading` feature to dynamically load Vulkan with `Entry`.

## 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/)
Expand Down
2 changes: 2 additions & 0 deletions ash/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ libloading = { version = "0.7", optional = true }

[features]
default = ["libloading"]
linked = []

[package.metadata.release]
no-dev-version = true

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
6 changes: 6 additions & 0 deletions ash/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
#[cfg(feature = "linked")]
{
println!("cargo:rustc-link-lib=vulkan");
}
}
8 changes: 6 additions & 2 deletions ash/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,24 @@ impl<L> EntryCustom<L> {
{
// Bypass the normal StaticFn::load so we can return an error
let static_fn = vk::StaticFn::load_checked(|name| load(&mut lib, name))?;
Ok(Self::from_static_fn(lib, static_fn))
}

pub unsafe fn from_static_fn(lib: L, 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()))
};
let entry_fn_1_0 = vk::EntryFnV1_0::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);

Ok(EntryCustom {
EntryCustom {
static_fn,
entry_fn_1_0,
entry_fn_1_1,
entry_fn_1_2,
lib,
})
}
}

pub fn fp_v1_0(&self) -> &vk::EntryFnV1_0 {
Expand Down
5 changes: 4 additions & 1 deletion ash/src/entry_libloading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ impl From<MissingEntryPoint> for LoadingError {
}
}

/// Default function loader
/// Runtime function loader
///
/// Prefer [`EntryLinked`](crate::EntryLinked) in code that would would otherwise panic on
/// [`Entry::new`] failing.
#[cfg_attr(docsrs, doc(cfg(feature = "libloading")))]
pub type Entry = EntryCustom<Arc<Library>>;

Expand Down
33 changes: 33 additions & 0 deletions ash/src/entry_linked.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::os::raw::c_char;

use crate::{entry::EntryCustom, vk};

/// Marker type for [`EntryLinked`]
pub struct Linked;

/// Compile-time function loader
///
/// Prefer this over [`Entry`](crate::Entry) in code that would otherwise panic on
/// [`Entry::new`](crate::Entry::new) failing.
#[cfg_attr(docsrs, doc(cfg(feature = "linked")))]
pub type EntryLinked = EntryCustom<Linked>;

impl EntryLinked {
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(
Linked,
vk::StaticFn {
get_instance_proc_addr: vkGetInstanceProcAddr,
},
)
}
}
}

extern "system" {
fn vkGetInstanceProcAddr(instance: vk::Instance, name: *const c_char)
-> vk::PFN_vkVoidFunction;
}
4 changes: 4 additions & 0 deletions ash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ pub use crate::device::Device;
pub use crate::entry::{EntryCustom, InstanceError};
#[cfg(feature = "libloading")]
pub use crate::entry_libloading::{Entry, LoadingError};
#[cfg(feature = "linked")]
pub use crate::entry_linked::EntryLinked;
pub use crate::instance::Instance;

mod device;
mod entry;
#[cfg(feature = "libloading")]
mod entry_libloading;
#[cfg(feature = "linked")]
mod entry_linked;
mod instance;
pub mod prelude;
pub mod util;
Expand Down
3 changes: 3 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ winit = "0.19.5"
image = "0.10.4"
ash = { path = "../ash" }
ash-window = { path = "../ash-window" }

[features]
linked = ["ash/linked"]
12 changes: 11 additions & 1 deletion examples/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ use ash::extensions::{
khr::{Surface, Swapchain},
};

use ash::{vk, Entry};
use ash::vk;
#[cfg(not(feature = "linked"))]
use ash::Entry;
#[cfg(feature = "linked")]
use ash::EntryLinked;
pub use ash::{Device, EntryCustom, Instance};
use std::borrow::Cow;
use std::cell::RefCell;
Expand Down Expand Up @@ -133,6 +137,9 @@ pub fn find_memorytype_index(
}

pub struct ExampleBase {
#[cfg(feature = "linked")]
pub entry: EntryLinked,
#[cfg(not(feature = "linked"))]
pub entry: Entry,
pub instance: Instance,
pub device: Device,
Expand Down Expand Up @@ -204,6 +211,9 @@ impl ExampleBase {
))
.build(&events_loop)
.unwrap();
#[cfg(feature = "linked")]
let entry = EntryLinked::new();
#[cfg(not(feature = "linked"))]
let entry = Entry::new().unwrap();
let app_name = CString::new("VulkanTriangle").unwrap();

Expand Down

0 comments on commit 33c291b

Please sign in to comment.