diff --git a/.gitignore b/.gitignore index 4fffb2f..7aeb431 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /target /Cargo.lock + +vk_functions \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..cae31dc --- /dev/null +++ b/build.rs @@ -0,0 +1,43 @@ +use std::{fs::File, io::Write, path::Path, process::Command, str::from_utf8}; + +const VK_INCLUDE: &str = "/usr/include/vulkan"; +const VK_HEADER: &[&str] = &[ + "vulkan_core.h", + "vulkan_xcb.h", + "vulkan_xlib.h", + "vulkan_wayland.h", +]; +const FN_PREFIX: &str = "PFN_"; + +fn main() { + let mut fns = Vec::new(); + + for header in VK_HEADER { + Command::new("ctags") + .arg("--help") + .output() + .expect("Failed to execute ctags. Maybe you need to install it first?"); + + let output = Command::new("ctags") + .arg("-x") + .arg("--c-types=t") + .arg(format!("{}/{}", VK_INCLUDE, header)) + .output() + .expect(&format!("failed to open file {}/{}", VK_INCLUDE, header)); + + let output_splits = from_utf8(&output.stdout).unwrap().split_whitespace(); + + for split in output_splits { + if split.starts_with(FN_PREFIX) { + fns.push(split.trim_start_matches(FN_PREFIX).to_string()) + } + } + } + + let path = Path::new("vk_functions"); + let mut file = File::create(path).unwrap(); + + for func in fns { + file.write_all(format!("{}\n", func).as_bytes()).unwrap(); + } +} diff --git a/src/lib.rs b/src/lib.rs index 68a8035..411de48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,15 +40,7 @@ pub extern "C" fn vkNegotiateLoaderLayerInterfaceVersion( } }; - set_vk_handles( - VkTypedefHandles::new(&[ - "vulkan_symbols/vulkan_core_symbols", - "vulkan_symbols/vulkan_wayland_symbols", - "vulkan_symbols/vulkan_xcb_symbols", - "vulkan_symbols/vulkan_xlib_symbols", - ]) - .unwrap(), - ); + set_vk_handles(VkTypedefHandles::new().unwrap()); VK_SUCCESS } @@ -77,6 +69,10 @@ extern "system" fn get_device_proc_addr( _ => (), }; + if let Some(func) = vk_handles().handle(s) { + return func; + } + write_log(format!("\trequested fn: {} in device proc addr", s)); write_log(format!("\t-> not found")); Functions::Null.convert() @@ -106,6 +102,10 @@ extern "system" fn get_instance_proc_addr( _ => (), }; + if let Some(func) = vk_handles().handle(s) { + return func; + } + write_log(format!("\trequested fn: {} in instance proc addr", s)); write_log(format!("\t-> not found")); Functions::Null.convert() @@ -152,6 +152,13 @@ extern "system" fn create_instance( extern "system" fn destroy_instance(instance: VkInstance, allocator: *const VkAllocationCallbacks) { write_log(" ================== vulkan layer destroy instance =================="); + + unsafe { + let destroy_instance: PFN_vkDestroyInstance = + mem::transmute(vk_handles().handle("vkDestroyInstance").unwrap()); + + destroy_instance(instance, allocator); + } } extern "system" fn create_device( @@ -194,9 +201,16 @@ extern "system" fn create_device( extern "system" fn destroy_device(device: VkDevice, allocator: *const VkAllocationCallbacks) { write_log(" ================== vulkan layer destroy device =================="); + + unsafe { + let destroy_device: PFN_vkDestroyDevice = + mem::transmute(vk_handles().handle("vkDestroyDevice").unwrap()); + + destroy_device(device, allocator); + } } -fn write_log(msg: impl ToString) { +pub fn write_log(msg: impl ToString) { let mut file = OpenOptions::new() .append(true) .create(true) diff --git a/src/vk_handles.rs b/src/vk_handles.rs index a81fdb5..28b0afd 100644 --- a/src/vk_handles.rs +++ b/src/vk_handles.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use std::{collections::HashMap, ffi::c_void, fs, mem, path::Path, ptr}; +use std::{collections::HashMap, ffi::c_void, mem, ptr}; use vulkan_sys::prelude::*; static mut FN_HANDLES: Option = None; @@ -24,14 +24,9 @@ pub struct VkTypedefHandles { } impl VkTypedefHandles { - pub fn new(symbol_files: &[impl AsRef]) -> Result { - let mut symbols = Vec::new(); - - for symbol_file in symbol_files { - let s = fs::read_to_string(symbol_file)?; - - symbols.append(&mut s.lines().map(|s| s.to_string()).collect()); - } + pub fn new() -> Result { + let fns = include_str!("../vk_functions"); + let symbols = fns.lines().map(|s| s.to_string()).collect(); Ok(Self { typedefs: symbols,