pub mod dummy_functions; pub mod enums; pub mod layer_device_dispatch_table; pub mod layer_instance_dispatch_table; pub mod structs; use std::{ fs::OpenOptions, io::Write, mem::{self}, os::raw::c_char, ptr, }; use enums::*; use structs::*; use vulkan_sys::prelude::*; static mut INSTANCE_FN_HANDLES: Option = None; fn instance_fns() -> &'static VkFunctionHandles { unsafe { INSTANCE_FN_HANDLES.as_ref().unwrap() } } pub struct VkFunctionHandles { pub static_functions: StaticFunctions, pub entry_functions: EntryFunctions, pub instance_functions: InstanceFunctions, pub instance_wsi_functions: InstanceWSIFunctions, pub physical_device_properties2_functions: PhysicalDeviceProperties2Functions, pub debug_report_callback_functions: DebugReportCallbackFunctions, pub debug_utils_messenger_functions: DebugUtilsMessengerFunctions, } impl VkFunctionHandles { pub fn load_instance( static_functions: StaticFunctions, entry_functions: EntryFunctions, instance: VkInstance, ) -> Self { Self { instance_functions: InstanceFunctions::new(&static_functions, instance), instance_wsi_functions: InstanceWSIFunctions::new(&static_functions, instance), physical_device_properties2_functions: PhysicalDeviceProperties2Functions::new( &static_functions, instance, ), debug_report_callback_functions: DebugReportCallbackFunctions::new( &static_functions, instance, ), debug_utils_messenger_functions: DebugUtilsMessengerFunctions::new( &static_functions, instance, ), static_functions, entry_functions, } } } macro_rules! cmp_vk_fn { ($name:ident, {$([$fns:ident, $fn_name:ident],)*}) => { match $name { $( stringify!($fn_name) => return unsafe { mem::transmute( instance_fns() .$fns .$fn_name, ) }, )* _ => () } } } #[no_mangle] #[allow(non_snake_case)] pub extern "C" fn vkNegotiateLoaderLayerInterfaceVersion( pVersionStruct: *mut VkNegotiateLayerInterface, ) -> VkResult { 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, } }; VK_SUCCESS } #[no_mangle] extern "system" fn get_device_proc_addr( device: VkDevice, function_name: *const c_char, ) -> PFN_vkVoidFunction { write_log("-> vulkan layer device proc addr"); get_function(function_name) } #[no_mangle] extern "system" fn get_instance_proc_addr( instance: VkInstance, function_name: *const c_char, ) -> PFN_vkVoidFunction { write_log("-> vulkan layer instance proc addr"); get_function(function_name) } fn get_function(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(); cmp_vk_fn!(s, { [debug_utils_messenger_functions, vkCreateDebugUtilsMessengerEXT], [debug_utils_messenger_functions, vkDestroyDebugUtilsMessengerEXT], [debug_report_callback_functions, vkCreateDebugReportCallbackEXT], [debug_report_callback_functions, vkDestroyDebugReportCallbackEXT], [instance_functions, vkEnumeratePhysicalDevices], [instance_functions, vkGetPhysicalDeviceFeatures], [instance_functions, vkGetPhysicalDeviceFormatProperties], [instance_functions, vkGetPhysicalDeviceImageFormatProperties], [instance_functions, vkGetPhysicalDeviceProperties], [instance_functions, vkGetPhysicalDeviceQueueFamilyProperties], [instance_functions, vkGetPhysicalDeviceMemoryProperties], [instance_functions, vkEnumerateDeviceExtensionProperties], // [instance_functions, vkEnumerateDeviceLayerProperties], [instance_functions, vkGetPhysicalDeviceSparseImageFormatProperties], // [instance_functions, vkEnumeratePhysicalDeviceGroups], [physical_device_properties2_functions, vkGetPhysicalDeviceFeatures2KHR], [physical_device_properties2_functions, vkGetPhysicalDeviceProperties2KHR], [physical_device_properties2_functions, vkGetPhysicalDeviceFormatProperties2KHR], [physical_device_properties2_functions, vkGetPhysicalDeviceFeatures2KHR], [physical_device_properties2_functions, vkGetPhysicalDeviceFeatures2KHR], [instance_wsi_functions, vkDestroySurfaceKHR], [instance_wsi_functions, vkGetPhysicalDeviceSurfaceSupportKHR], [instance_wsi_functions, vkGetPhysicalDeviceSurfaceCapabilitiesKHR], [instance_wsi_functions, vkGetPhysicalDeviceSurfaceFormatsKHR], [instance_wsi_functions, vkGetPhysicalDeviceSurfacePresentModesKHR], [instance_wsi_functions, vkGetPhysicalDeviceDisplayPropertiesKHR], [instance_wsi_functions, vkGetPhysicalDeviceDisplayPlanePropertiesKHR], [instance_wsi_functions, vkGetDisplayPlaneSupportedDisplaysKHR], [instance_wsi_functions, vkGetDisplayModePropertiesKHR], [instance_wsi_functions, vkCreateDisplayModeKHR], [instance_wsi_functions, vkGetDisplayPlaneCapabilitiesKHR], [instance_wsi_functions, vkCreateDisplayPlaneSurfaceKHR], [instance_wsi_functions, vkCreateXlibSurfaceKHR], [instance_wsi_functions, vkGetPhysicalDeviceXlibPresentationSupportKHR], [instance_wsi_functions, vkCreateXcbSurfaceKHR], [instance_wsi_functions, vkGetPhysicalDeviceXcbPresentationSupportKHR], [instance_wsi_functions, vkCreateWaylandSurfaceKHR], [instance_wsi_functions, vkGetPhysicalDeviceWaylandPresentationSupportKHR], } ); match s { "vkCreateDevice" => Functions::CreateDevice(create_device), "vkDestroyDevice" => Functions::DestroyDevice(destroy_device), "vkCreateInstance" => Functions::CreateInstance(create_instance), "vkDestroyInstance" => Functions::DestroyInstance(destroy_instance), _ => { write_log(format!("\trequested fn: {}", 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("chain info not found."); return VK_ERROR_LAYER_NOT_PRESENT; } }; let proc_addr = chain_info.layer_info().next_instance_proc_addr; let static_functions = StaticFunctions { _lib: None, vkGetInstanceProcAddr: proc_addr, }; let entry_functions = EntryFunctions::new(&static_functions); chain_info.advance_layer_info(); let result = unsafe { entry_functions.vkCreateInstance(create_info, allocator, instance) }; if result != VK_SUCCESS { return result; } let function_handles = VkFunctionHandles::load_instance(static_functions, entry_functions, unsafe { *instance }); unsafe { INSTANCE_FN_HANDLES = Some(function_handles) }; write_log("-> successfully created instance."); VK_SUCCESS } extern "system" fn destroy_instance(instance: VkInstance, allocator: *const VkAllocationCallbacks) { write_log(" ================== vulkan layer destroy instance =================="); } 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 =================="); VK_SUCCESS } extern "system" fn destroy_device(device: VkDevice, allocator: *const VkAllocationCallbacks) { write_log(" ================== vulkan layer destroy device =================="); } fn write_log(msg: impl ToString) { let mut file = OpenOptions::new() .append(true) .create(true) .open("/home/michael/rf2_vk_hud.log") .unwrap(); file.write_all(format!("{}\n", msg.to_string()).as_bytes()) .unwrap(); }