mirror of
https://github.com/italicsjenga/ash-molten.git
synced 2024-12-23 21:31:30 +11:00
lib: Provide entrypoint through Ash loader w.o. implementing Entry (#56)
* 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]: https://github.com/MaikKlein/ash/pull/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
This commit is contained in:
parent
61ec5fda40
commit
2d8c62373f
|
@ -14,7 +14,7 @@ documentation = "https://docs.rs/ash-molten"
|
||||||
build = "build/build.rs"
|
build = "build/build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ash = "0.32"
|
ash = { version = "0.33", default-features = false }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|
|
@ -13,15 +13,15 @@ Requires Xcode 12 and Mac OS 10.15 (Catalina) to compile.
|
||||||
|
|
||||||
## Why?
|
## 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.
|
* You just want to try out [MoltenVK](https://github.com/KhronosGroup/MoltenVK) without needing to setup the SDK.
|
||||||
|
|
||||||
## Why not?
|
## 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?
|
## How?
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ mod mac {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Features are not used inside build scripts, so we have to explicitly query them from the
|
// 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 {
|
pub(crate) fn is_feature_enabled(feature: &str) -> bool {
|
||||||
std::env::vars()
|
std::env::vars()
|
||||||
.filter_map(|(flag, _)| {
|
.filter_map(|(flag, _)| {
|
||||||
|
@ -186,7 +186,7 @@ mod mac {
|
||||||
"ios" => ("ios", "iOS"),
|
"ios" => ("ios", "iOS"),
|
||||||
target => panic!("unknown target '{}'", target),
|
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")
|
let status = Command::new("sh")
|
||||||
|
@ -274,7 +274,7 @@ use std::{
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
fn main() {
|
fn main() {
|
||||||
use crate::mac::*;
|
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 external_enabled = is_feature_enabled("EXTERNAL");
|
||||||
let pre_built_enabled = is_feature_enabled("PRE_BUILT");
|
let pre_built_enabled = is_feature_enabled("PRE_BUILT");
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ fn main() {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!(external_enabled && pre_built_enabled),
|
!(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 {
|
if !external_enabled {
|
||||||
|
|
|
@ -70,14 +70,11 @@
|
||||||
// crate-specific exceptions:
|
// crate-specific exceptions:
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use ash::{
|
use ash::vk;
|
||||||
version::{EntryV1_0, InstanceV1_0},
|
|
||||||
vk,
|
|
||||||
};
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
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 app_name = CString::new("Hello Static Molten").unwrap();
|
||||||
|
|
||||||
let appinfo = vk::ApplicationInfo::builder()
|
let appinfo = vk::ApplicationInfo::builder()
|
||||||
|
@ -85,7 +82,7 @@ fn main() {
|
||||||
.application_version(0)
|
.application_version(0)
|
||||||
.engine_name(&app_name)
|
.engine_name(&app_name)
|
||||||
.engine_version(0)
|
.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 create_info = vk::InstanceCreateInfo::builder().application_info(&appinfo);
|
||||||
let instance = entry.create_instance(&create_info, None).expect("Instance");
|
let instance = entry.create_instance(&create_info, None).expect("Instance");
|
||||||
|
|
72
src/lib.rs
72
src/lib.rs
|
@ -70,7 +70,9 @@
|
||||||
// crate-specific exceptions:
|
// crate-specific exceptions:
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use ash::{version::EntryV1_0, vk, Instance, InstanceError, RawPtr};
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use ash::{vk, EntryCustom};
|
||||||
|
|
||||||
extern "system" {
|
extern "system" {
|
||||||
fn vkGetInstanceProcAddr(
|
fn vkGetInstanceProcAddr(
|
||||||
|
@ -79,62 +81,28 @@ extern "system" {
|
||||||
) -> vk::PFN_vkVoidFunction;
|
) -> 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
|
/// The entry point for the statically linked molten library
|
||||||
pub struct MoltenEntry {
|
pub struct MoltenEntry(EntryCustom<()>);
|
||||||
static_fn: vk::StaticFn,
|
|
||||||
entry_fn_1_0: vk::EntryFnV1_0,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MoltenEntry {
|
impl MoltenEntry {
|
||||||
/// Fetches the function pointer to `get_instance_proc_addr` which is statically linked. This
|
/// Fetches the function pointer to `vkGetInstanceProcAddr` which is statically linked.
|
||||||
/// function can not fail.
|
pub fn load() -> Self {
|
||||||
pub fn load() -> Result<MoltenEntry, ash::LoadingError> {
|
Self(
|
||||||
let static_fn = vk::StaticFn {
|
EntryCustom::new_custom((), |(), name| {
|
||||||
get_instance_proc_addr,
|
assert_eq!(name.to_bytes_with_nul(), b"vkGetInstanceProcAddr\0");
|
||||||
};
|
vkGetInstanceProcAddr as _
|
||||||
|
|
||||||
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,
|
|
||||||
})
|
})
|
||||||
|
// This can never fail because we always return the address of
|
||||||
|
// `vkGetInstanceProcAddr` from the closure:
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl EntryV1_0 for MoltenEntry {
|
|
||||||
type Instance = Instance;
|
impl Deref for MoltenEntry {
|
||||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCreateInstance.html>"]
|
type Target = EntryCustom<()>;
|
||||||
unsafe fn create_instance(
|
|
||||||
&self,
|
fn deref(&self) -> &Self::Target {
|
||||||
create_info: &vk::InstanceCreateInfo,
|
&self.0
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue