commit 629897604de7d9b66c0c18dd3d3749a23b900b3b Author: Maik Klein Date: Wed Jun 5 10:22:29 2019 +0200 Init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f88dba --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9f42f75 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ash-molten" +version = "0.1.0" +authors = ["maik "] +edition = "2018" + +[dependencies] + +ash = "0.29" diff --git a/README.md b/README.md new file mode 100644 index 0000000..59013f5 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# ash-molten + + +`ash-molten` statically links with molten and exposes a new entry point `MoltenEntry`. The function pointers are still fetched at runtime via `getInstanceProcAddr`. + +Use this if want to compile down to a single executable. Runtime linking is always preferred and you lose access to the validation layers if you use `ash-molten`. + +``` +let entry = ash_molten::MoltenEntry::load().expect("Unable to load Molten"); +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)); + +let create_info = vk::InstanceCreateInfo::builder().application_info(&appinfo); +let instance = entry.create_instance(&create_info, None).expect("Instance"); +let devices = instance.enumerate_physical_devices(); +println!("{:?}", devices); +``` diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..d134a7e --- /dev/null +++ b/build.rs @@ -0,0 +1,14 @@ +use std::path::PathBuf; +fn main() { + let project_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("external"); + println!("cargo:rustc-link-search=native={}", project_dir.display()); + println!("cargo:rustc-link-lib=framework=Foundation"); + println!("cargo:rustc-link-lib=framework=Metal"); + println!("cargo:rustc-link-lib=framework=AppKit"); + println!("cargo:rustc-link-lib=framework=CoreGraphics"); + println!("cargo:rustc-link-lib=framework=QuartzCore"); + println!("cargo:rustc-link-lib=framework=IOKit"); + println!("cargo:rustc-link-lib=framework=IOSurface"); + println!("cargo:rustc-link-lib=dylib=c++"); + println!("cargo:rustc-link-lib=static=MoltenVK"); +} diff --git a/external/libMoltenVK.a b/external/libMoltenVK.a new file mode 100644 index 0000000..bad86c1 Binary files /dev/null and b/external/libMoltenVK.a differ diff --git a/src/bin/main.rs b/src/bin/main.rs new file mode 100644 index 0000000..396ed40 --- /dev/null +++ b/src/bin/main.rs @@ -0,0 +1,23 @@ +use ash::{ + version::{EntryV1_0, InstanceV1_0}, + vk, vk_make_version, +}; +use std::ffi::CString; +fn main() { + unsafe { + let entry = ash_molten::MoltenEntry::load().expect("Unable to load Molten"); + 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)); + + let create_info = vk::InstanceCreateInfo::builder().application_info(&appinfo); + let instance = entry.create_instance(&create_info, None).expect("Instance"); + let devices = instance.enumerate_physical_devices(); + println!("{:?}", devices); + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..16103a0 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,69 @@ +extern crate ash; +use ash::{version::EntryV1_0, vk, Instance, InstanceError, RawPtr}; + +extern "system" { + fn vkGetInstanceProcAddr( + instance: vk::Instance, + p_name: *const std::os::raw::c_char, + ) -> 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, +} + +impl MoltenEntry { + /// Fetches the function pointer to `get_instance_proc_addr` which is statically linked. This + /// function can not fail. + pub fn load() -> Result { + let static_fn = vk::StaticFn { + get_instance_proc_addr: 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, + }) + } +} +impl EntryV1_0 for MoltenEntry { + type Instance = Instance; + #[doc = ""] + unsafe fn create_instance( + &self, + create_info: &vk::InstanceCreateInfo, + allocation_callbacks: Option<&vk::AllocationCallbacks>, + ) -> Result { + 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 + } +}