Skip to content

Commit

Permalink
lib: Provide entrypoint through Ash loader w.o. implementing Entry (#56)
Browse files Browse the repository at this point in the history
* lib: Provide entrypoint through Ash loader w.o. implementing Entry

Ash recently [dropped all traits](1) to simplify `ash::Device` usage,
but this also disallows ash-molten from overriding the `EntryV1_0` trait
to provide a static entrypoint intead.

Fortunately ash-molten can simply pass a library loading closure that
returns the static address of `vkGetInstanceProcAddr` to
`EntryCustom::new_custom`, getting rid of the copied `fn
create_instance` implementation at the same time.

[1]: ash-rs/ash#412

* cargo: Disable unneeded `libloading` feature in Ash

The entry-point is statically linked from `MoltenVK` and does not need
any dlopen nor dlsym functionality.

* Fix some typos
  • Loading branch information
MarijnS95 authored Oct 14, 2021
1 parent 61ec5fd commit 2d8c623
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 69 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ documentation = "https://docs.rs/ash-molten"
build = "build/build.rs"

[dependencies]
ash = "0.32"
ash = { version = "0.33", default-features = false }

[build-dependencies]
anyhow = "1.0"
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ Requires Xcode 12 and Mac OS 10.15 (Catalina) to compile.

## Why?

* You want to compile down to a single binary that doesn't need any enviroment variables to bet set.
* You want to compile down to a single binary that doesn't need any environment variables to bet set.

* You just want to try out [MoltenVK](https://github.com/KhronosGroup/MoltenVK) without needing to setup the SDK.

## Why not?

* [ash](https://github.com/MaikKlein/ash) already supports [MoltenVK](https://github.com/KhronosGroup/MoltenVK) via runtime linking. Runtime linking is the prefered way of using Vulkan because the loader can be updated at anytime without needing to recompile.
* [ash](https://github.com/MaikKlein/ash) already supports [MoltenVK](https://github.com/KhronosGroup/MoltenVK) via runtime linking. Runtime linking is the preferred way of using Vulkan because the loader can be updated at anytime without needing to recompile.

* `ash-molten` doesn't have access to the validation layers and thefore can not output any debug information.
* `ash-molten` doesn't have access to the validation layers and therefore can not output any debug information.

## How?

Expand Down Expand Up @@ -62,7 +62,7 @@ To update the version of [MoltenVK](https://github.com/KhronosGroup/MoltenVK) us
- In `build.rs`, change `static VERSION = "1.1.0"` to the new [MoltenVK release](https://github.com/KhronosGroup/MoltenVK/releases) tag name
- Update the crate version in `Cargo.toml`
- Bump the patch version
- Set the version metadata to the MoltenVK release.
- Set the version metadata to the MoltenVK release.
- E.g. `0.2.0+37` -> `0.2.1+38`.

### Updating pre-built version
Expand Down
10 changes: 5 additions & 5 deletions build/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ mod mac {
}

// Features are not used inside build scripts, so we have to explicitly query them from the
// enviroment
// environment
pub(crate) fn is_feature_enabled(feature: &str) -> bool {
std::env::vars()
.filter_map(|(flag, _)| {
Expand Down Expand Up @@ -136,7 +136,7 @@ mod mac {
});

if Path::new(&checkout_dir).exists() {
// Don't pull if a specific hash has been checkedout
// Don't pull if a specific hash has been checked out
if MOLTEN_VK_PATCH.is_none() {
let git_status = Command::new("git")
.current_dir(&checkout_dir)
Expand Down Expand Up @@ -186,7 +186,7 @@ mod mac {
"ios" => ("ios", "iOS"),
target => panic!("unknown target '{}'", target),
},
Err(e) => panic!("failed to determinte target os '{}'", e),
Err(e) => panic!("failed to determine target os '{}'", e),
};

let status = Command::new("sh")
Expand Down Expand Up @@ -274,7 +274,7 @@ use std::{
#[cfg(any(target_os = "macos", target_os = "ios"))]
fn main() {
use crate::mac::*;
// The 'external' feature was not enabled. Molten will be built automaticaly.
// The 'external' feature was not enabled. Molten will be built automatically.
let external_enabled = is_feature_enabled("EXTERNAL");
let pre_built_enabled = is_feature_enabled("PRE_BUILT");

Expand All @@ -283,7 +283,7 @@ fn main() {

assert!(
!(external_enabled && pre_built_enabled),
"external and prebuild cannot be active at the same time"
"external and prebuilt cannot be active at the same time"
);

if !external_enabled {
Expand Down
9 changes: 3 additions & 6 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,19 @@
// crate-specific exceptions:
#![allow(unsafe_code)]

use ash::{
version::{EntryV1_0, InstanceV1_0},
vk,
};
use ash::vk;
use std::ffi::CString;
fn main() {
unsafe {
let entry = ash_molten::MoltenEntry::load().expect("Unable to load Molten");
let entry = ash_molten::MoltenEntry::load();
let app_name = CString::new("Hello Static Molten").unwrap();

let appinfo = vk::ApplicationInfo::builder()
.application_name(&app_name)
.application_version(0)
.engine_name(&app_name)
.engine_version(0)
.api_version(vk::make_version(1, 0, 0));
.api_version(vk::make_api_version(0, 1, 0, 0));

let create_info = vk::InstanceCreateInfo::builder().application_info(&appinfo);
let instance = entry.create_instance(&create_info, None).expect("Instance");
Expand Down
74 changes: 21 additions & 53 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@
// crate-specific exceptions:
#![allow(unsafe_code)]

use ash::{version::EntryV1_0, vk, Instance, InstanceError, RawPtr};
use std::ops::Deref;

use ash::{vk, EntryCustom};

extern "system" {
fn vkGetInstanceProcAddr(
Expand All @@ -79,62 +81,28 @@ extern "system" {
) -> vk::PFN_vkVoidFunction;
}

extern "system" fn get_instance_proc_addr(
instance: vk::Instance,
p_name: *const std::os::raw::c_char,
) -> vk::PFN_vkVoidFunction {
unsafe { vkGetInstanceProcAddr(instance, p_name) }
}

/// The entry point for the statically linked molten library
pub struct MoltenEntry {
static_fn: vk::StaticFn,
entry_fn_1_0: vk::EntryFnV1_0,
}
pub struct MoltenEntry(EntryCustom<()>);

impl MoltenEntry {
/// Fetches the function pointer to `get_instance_proc_addr` which is statically linked. This
/// function can not fail.
pub fn load() -> Result<MoltenEntry, ash::LoadingError> {
let static_fn = vk::StaticFn {
get_instance_proc_addr,
};

let entry_fn_1_0 = vk::EntryFnV1_0::load(|name| unsafe {
std::mem::transmute(
static_fn.get_instance_proc_addr(vk::Instance::null(), name.as_ptr()),
)
});

Ok(MoltenEntry {
static_fn,
entry_fn_1_0,
})
/// Fetches the function pointer to `vkGetInstanceProcAddr` which is statically linked.
pub fn load() -> Self {
Self(
EntryCustom::new_custom((), |(), name| {
assert_eq!(name.to_bytes_with_nul(), b"vkGetInstanceProcAddr\0");
vkGetInstanceProcAddr as _
})
// This can never fail because we always return the address of
// `vkGetInstanceProcAddr` from the closure:
.unwrap(),
)
}
}
impl EntryV1_0 for MoltenEntry {
type Instance = Instance;
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCreateInstance.html>"]
unsafe fn create_instance(
&self,
create_info: &vk::InstanceCreateInfo,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) -> Result<Self::Instance, InstanceError> {
let mut instance: vk::Instance = vk::Instance::null();
let err_code = self.fp_v1_0().create_instance(
create_info,
allocation_callbacks.as_raw_ptr(),
&mut instance,
);
if err_code != vk::Result::SUCCESS {
return Err(InstanceError::VkError(err_code));
}
Ok(Instance::load(&self.static_fn, instance))
}
fn fp_v1_0(&self) -> &vk::EntryFnV1_0 {
&self.entry_fn_1_0
}
fn static_fn(&self) -> &vk::StaticFn {
&self.static_fn

impl Deref for MoltenEntry {
type Target = EntryCustom<()>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

0 comments on commit 2d8c623

Please sign in to comment.