diff --git a/src/enums.rs b/src/enums.rs index 1f30d8c..5eb56ae 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -25,6 +25,8 @@ pub enum Functions { DestroyInstance(PFN_vkDestroyInstance), CreateDevice(PFN_vkCreateDevice), DestroyDevice(PFN_vkDestroyDevice), + CreateSwapchain(PFN_vkCreateSwapchainKHR), + QueueSubmit(PFN_vkQueueSubmit), } impl Functions { @@ -37,6 +39,8 @@ impl Functions { Functions::DestroyInstance(func) => unsafe { mem::transmute(func) }, Functions::CreateDevice(func) => unsafe { mem::transmute(func) }, Functions::DestroyDevice(func) => unsafe { mem::transmute(func) }, + Functions::CreateSwapchain(func) => unsafe { mem::transmute(func) }, + Functions::QueueSubmit(func) => unsafe { mem::transmute(func) }, } } } diff --git a/src/lib.rs b/src/lib.rs index 61bdfd0..646c3a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,11 +4,13 @@ pub mod structs; mod vk_handles; use std::{ + ffi::c_void, fs::{File, OpenOptions}, io::Write, mem, os::raw::c_char, ptr, + sync::Arc, }; use enums::*; @@ -18,6 +20,20 @@ use vulkan_rs::prelude::*; const LOG_FILE: &'static str = "/home/michael/rf2_vk_hud.log"; +static mut INSTANCE: Option> = None; +static mut DEVICE: Option> = None; +static mut SWAPCHAIN: Option> = None; +static mut QUEUE_SUBMIT: PFN_vkQueueSubmit = + unsafe { mem::transmute(vkVoidFunction as *const c_void) }; + +pub fn instance() -> Arc { + unsafe { INSTANCE.as_ref().unwrap().clone() } +} + +pub fn device() -> Arc { + unsafe { DEVICE.as_ref().unwrap().clone() } +} + #[no_mangle] #[allow(non_snake_case)] pub extern "C" fn vkNegotiateLoaderLayerInterfaceVersion( @@ -60,21 +76,16 @@ extern "system" fn get_device_proc_addr( 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) = get_vk_func(s) { + return func.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")); + // write_log(format!("\trequested fn: {} in device proc addr", s)); + // write_log(format!("\t-> not found")); Functions::Null.convert() } @@ -93,21 +104,16 @@ extern "system" fn get_instance_proc_addr( 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) = get_vk_func(s) { + return func.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")); + // write_log(format!("\trequested fn: {} in instance proc addr", s)); + // write_log(format!("\t-> not found")); Functions::Null.convert() } @@ -147,6 +153,32 @@ extern "system" fn create_instance( write_log("-> successfully created instance."); + let ext_names = unsafe { (*create_info).extension_names() }; + + write_log(format!("{:?}", ext_names)); + + // DXVK workaround, it creates the instance twice with different properties + if ext_names.contains(&VkString::new("VK_KHR_surface")) { + unsafe { + let ins = match Instance::preinitialized( + *instance, + proc_addr, + &ext_names, + (*(*create_info).pApplicationInfo).apiVersion, + ) { + Ok(ins) => ins, + Err(err) => { + write_log(format!("-> local instance creation failed: {:?}", err)); + return VK_ERROR_INITIALIZATION_FAILED; + } + }; + + INSTANCE = Some(ins); + } + + write_log("-> created local instance handle"); + } + VK_SUCCESS } @@ -195,6 +227,25 @@ extern "system" fn create_device( } vk_handles_mut().load_device_functions(unsafe { *device }, proc_addr); + unsafe { QUEUE_SUBMIT = mem::transmute(vk_handles().handle("vkQueueSubmit").unwrap()) }; + + let pdev = PhysicalDevice::from_raw(instance(), physical_device).unwrap(); + + let ext_names = unsafe { (*create_info).extension_names() }; + + write_log(format!("{:?}", ext_names)); + + unsafe { + DEVICE = Some( + match Device::preinitialized(*device, proc_addr, pdev, &ext_names) { + Ok(dev) => dev, + Err(err) => { + write_log(format!("-> local device creation failed: {:?}", err)); + return VK_ERROR_INITIALIZATION_FAILED; + } + }, + ); + } VK_SUCCESS } @@ -210,6 +261,31 @@ extern "system" fn destroy_device(device: VkDevice, allocator: *const VkAllocati } } +extern "system" fn create_swapchain( + _device: VkDevice, + create_info: *const VkSwapchainCreateInfoKHR, + _allocator: *const VkAllocationCallbacks, + p_swapchain: *mut VkSwapchainKHR, +) -> VkResult { + write_log(" ================== vulkan layer create swapchain =================="); + + let swapchain = Swapchain::from_ci(device(), unsafe { &*create_info }).unwrap(); + + unsafe { *p_swapchain = swapchain.vk_handle() }; + unsafe { SWAPCHAIN = Some(swapchain) }; + + VK_SUCCESS +} + +extern "system" fn submit_queue( + queue: VkQueue, + submit_count: u32, + submits: *const VkSubmitInfo, + fence: VkFence, +) -> VkResult { + unsafe { QUEUE_SUBMIT(queue, submit_count, submits, fence) } +} + pub fn write_log(msg: impl ToString) { let mut file = OpenOptions::new() .append(true) @@ -220,3 +296,16 @@ pub fn write_log(msg: impl ToString) { file.write_all(format!("{}\n", msg.to_string()).as_bytes()) .unwrap(); } + +pub fn get_vk_func(s: &str) -> Option { + match s { + "vkCreateDevice" => Some(Functions::CreateDevice(create_device)), + "vkDestroyDevice" => Some(Functions::DestroyDevice(destroy_device)), + "vkCreateInstance" => Some(Functions::CreateInstance(create_instance)), + "vkDestroyInstance" => Some(Functions::DestroyInstance(destroy_instance)), + "vkCreateSwapchainKHR" => Some(Functions::CreateSwapchain(create_swapchain)), + "vkQueueSubmit" => Some(Functions::QueueSubmit(submit_queue)), + + _ => None, + } +}