pub mod enums; pub mod structs; mod vk_handles; use std::{ fs::{File, OpenOptions}, io::Write, mem, os::raw::c_char, ptr, }; use enums::*; use structs::*; use vk_handles::*; use vulkan_sys::prelude::*; const LOG_FILE: &'static str = "/home/michael/rf2_vk_hud.log"; #[no_mangle] #[allow(non_snake_case)] pub extern "C" fn vkNegotiateLoaderLayerInterfaceVersion( pVersionStruct: *mut VkNegotiateLayerInterface, ) -> VkResult { File::create(LOG_FILE).unwrap(); write_log(" =================================================================="); write_log(" ======================= New Negotiation =========================="); write_log(" =================================================================="); unsafe { *pVersionStruct = VkNegotiateLayerInterface { sType: enums::VkNegotiateLayerStructType::LAYER_NEGOTIATE_INTERFACE_STRUCT, pNext: ptr::null_mut(), loaderLayerInterfaceVersion: 2, pfnGetInstanceProcAddr: Some(get_instance_proc_addr), pfnGetDeviceProcAddr: Some(get_device_proc_addr), pfnGetPhysicalDeviceProcAddr: None, } }; set_vk_handles(VkTypedefHandles::new().unwrap()); VK_SUCCESS } #[no_mangle] extern "system" fn get_device_proc_addr( _device: VkDevice, function_name: *const c_char, ) -> PFN_vkVoidFunction { let func_string = match VkString::try_from(function_name) { Ok(func) => func, Err(_) => { write_log("Err: failed creating string"); return Functions::Null.convert(); } }; let s = func_string.as_str(); match s { "vkCreateDevice" => return Functions::CreateDevice(create_device).convert(), "vkDestroyDevice" => return Functions::DestroyDevice(destroy_device).convert(), "vkCreateInstance" => return Functions::CreateInstance(create_instance).convert(), "vkDestroyInstance" => return Functions::DestroyInstance(destroy_instance).convert(), _ => (), }; 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() } #[no_mangle] extern "system" fn get_instance_proc_addr( _instance: VkInstance, function_name: *const c_char, ) -> PFN_vkVoidFunction { let func_string = match VkString::try_from(function_name) { Ok(func) => func, Err(_) => { write_log("Err: failed creating string"); return Functions::Null.convert(); } }; let s = func_string.as_str(); match s { "vkCreateDevice" => return Functions::CreateDevice(create_device).convert(), "vkDestroyDevice" => return Functions::DestroyDevice(destroy_device).convert(), "vkCreateInstance" => return Functions::CreateInstance(create_instance).convert(), "vkDestroyInstance" => return Functions::DestroyInstance(destroy_instance).convert(), _ => (), }; 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() } extern "system" fn create_instance( create_info: *const VkInstanceCreateInfo, allocator: *const VkAllocationCallbacks, instance: *mut VkInstance, ) -> VkResult { write_log(" ================== vulkan layer create instance =================="); let chain_info = match VkLayerInstanceCreateInfo::get_chain_info( unsafe { &*create_info }, VK_LAYER_LINK_INFO, ) { Some(info) => info, None => { write_log("instance chain info not found."); return VK_ERROR_LAYER_NOT_PRESENT; } }; let proc_addr = chain_info.layer_info().next_instance_proc_addr; let create_instance: PFN_vkCreateInstance = unsafe { mem::transmute(proc_addr( VkInstance::NULL_HANDLE, VkString::new("vkCreateInstance").as_ptr(), )) }; chain_info.advance_layer_info(); let result = create_instance(create_info, allocator, instance); if result != VK_SUCCESS { return result; }; vk_handles_mut().load_instance_functions(unsafe { *instance }, proc_addr); write_log("-> successfully created instance."); VK_SUCCESS } 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( physical_device: VkPhysicalDevice, create_info: *const VkDeviceCreateInfo<'_>, allocator: *const VkAllocationCallbacks, device: *mut VkDevice, ) -> VkResult { write_log(" ================== vulkan layer create device =================="); let chain_info = match VkLayerDeviceCreateInfo::get_chain_info(unsafe { &*create_info }, VK_LAYER_LINK_INFO) { Some(info) => info, None => { write_log("device chain info not found."); return VK_ERROR_LAYER_NOT_PRESENT; } }; let proc_addr = chain_info.layer_info().next_device_proc_addr; chain_info.advance_layer_info(); let result = unsafe { let create_device: PFN_vkCreateDevice = mem::transmute(vk_handles().handle("vkCreateDevice").unwrap()); create_device(physical_device, create_info, allocator, device) }; if result != VK_SUCCESS { return result; } vk_handles_mut().load_device_functions(unsafe { *device }, proc_addr); VK_SUCCESS } 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); } } pub fn write_log(msg: impl ToString) { let mut file = OpenOptions::new() .append(true) .create(true) .open(LOG_FILE) .unwrap(); file.write_all(format!("{}\n", msg.to_string()).as_bytes()) .unwrap(); }