rFactor2_vk_hud/src/lib.rs

312 lines
9 KiB
Rust
Raw Normal View History

2023-01-10 13:24:04 +00:00
pub mod enums;
pub mod structs;
2023-01-11 14:03:32 +00:00
mod vk_handles;
2023-01-10 13:24:04 +00:00
2023-01-10 18:33:45 +00:00
use std::{
2023-01-12 08:17:24 +00:00
ffi::c_void,
2023-01-10 18:33:45 +00:00
fs::{File, OpenOptions},
io::Write,
mem,
os::raw::c_char,
ptr,
2023-01-12 08:17:24 +00:00
sync::Arc,
2023-01-10 18:33:45 +00:00
};
2023-01-10 17:20:18 +00:00
2023-01-10 13:24:04 +00:00
use enums::*;
use structs::*;
2023-01-11 14:03:32 +00:00
use vk_handles::*;
2023-01-11 20:46:17 +00:00
use vulkan_rs::prelude::*;
2023-01-10 13:24:04 +00:00
2023-01-10 18:33:45 +00:00
const LOG_FILE: &'static str = "/home/michael/rf2_vk_hud.log";
2023-01-12 08:17:24 +00:00
static mut INSTANCE: Option<Arc<Instance>> = None;
static mut DEVICE: Option<Arc<Device>> = None;
static mut SWAPCHAIN: Option<Arc<Swapchain>> = None;
static mut QUEUE_SUBMIT: PFN_vkQueueSubmit =
unsafe { mem::transmute(vkVoidFunction as *const c_void) };
pub fn instance() -> Arc<Instance> {
unsafe { INSTANCE.as_ref().unwrap().clone() }
}
pub fn device() -> Arc<Device> {
unsafe { DEVICE.as_ref().unwrap().clone() }
}
2023-01-10 13:24:04 +00:00
#[no_mangle]
#[allow(non_snake_case)]
pub extern "C" fn vkNegotiateLoaderLayerInterfaceVersion(
pVersionStruct: *mut VkNegotiateLayerInterface,
) -> VkResult {
2023-01-10 18:33:45 +00:00
File::create(LOG_FILE).unwrap();
write_log(" ==================================================================");
write_log(" ======================= New Negotiation ==========================");
write_log(" ==================================================================");
2023-01-10 13:24:04 +00:00
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,
}
};
2023-01-11 17:51:31 +00:00
set_vk_handles(VkTypedefHandles::new().unwrap());
2023-01-11 14:03:32 +00:00
2023-01-10 13:24:04 +00:00
VK_SUCCESS
}
#[no_mangle]
extern "system" fn get_device_proc_addr(
2023-01-10 17:20:18 +00:00
_device: VkDevice,
2023-01-10 13:24:04 +00:00
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();
}
};
2023-01-10 15:56:56 +00:00
let s = func_string.as_str();
2023-01-12 08:17:24 +00:00
if let Some(func) = get_vk_func(s) {
return func.convert();
}
2023-01-10 18:41:45 +00:00
2023-01-11 17:51:31 +00:00
if let Some(func) = vk_handles().handle(s) {
return func;
}
2023-01-12 08:17:24 +00:00
// write_log(format!("\trequested fn: {} in device proc addr", s));
// write_log(format!("\t-> not found"));
2023-01-10 18:41:45 +00:00
Functions::Null.convert()
2023-01-10 13:24:04 +00:00
}
#[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();
2023-01-11 05:00:35 +00:00
}
};
2023-01-11 05:00:35 +00:00
let s = func_string.as_str();
2023-01-11 05:00:35 +00:00
2023-01-12 08:17:24 +00:00
if let Some(func) = get_vk_func(s) {
return func.convert();
}
2023-01-11 17:51:31 +00:00
if let Some(func) = vk_handles().handle(s) {
return func;
}
2023-01-12 08:17:24 +00:00
// write_log(format!("\trequested fn: {} in instance proc addr", s));
// write_log(format!("\t-> not found"));
Functions::Null.convert()
2023-01-11 05:00:35 +00:00
}
2023-01-10 13:24:04 +00:00
extern "system" fn create_instance(
create_info: *const VkInstanceCreateInfo,
allocator: *const VkAllocationCallbacks,
instance: *mut VkInstance,
) -> VkResult {
2023-01-10 15:56:56 +00:00
write_log(" ================== vulkan layer create instance ==================");
2023-01-10 13:24:04 +00:00
let chain_info = match VkLayerInstanceCreateInfo::get_chain_info(
unsafe { &*create_info },
VK_LAYER_LINK_INFO,
) {
Some(info) => info,
None => {
2023-01-10 17:20:18 +00:00
write_log("instance chain info not found.");
2023-01-10 13:24:04 +00:00
return VK_ERROR_LAYER_NOT_PRESENT;
}
};
let proc_addr = chain_info.layer_info().next_instance_proc_addr;
2023-01-11 14:03:32 +00:00
let create_instance: PFN_vkCreateInstance = unsafe {
mem::transmute(proc_addr(
VkInstance::NULL_HANDLE,
VkString::new("vkCreateInstance").as_ptr(),
))
2023-01-10 13:24:04 +00:00
};
chain_info.advance_layer_info();
2023-01-11 14:03:32 +00:00
let result = create_instance(create_info, allocator, instance);
2023-01-10 13:24:04 +00:00
if result != VK_SUCCESS {
return result;
2023-01-10 17:20:18 +00:00
};
2023-01-10 15:56:56 +00:00
2023-01-11 14:03:32 +00:00
vk_handles_mut().load_instance_functions(unsafe { *instance }, proc_addr);
2023-01-10 15:56:56 +00:00
write_log("-> successfully created instance.");
2023-01-10 13:24:04 +00:00
2023-01-12 08:17:24 +00:00
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");
}
2023-01-10 13:24:04 +00:00
VK_SUCCESS
}
extern "system" fn destroy_instance(instance: VkInstance, allocator: *const VkAllocationCallbacks) {
2023-01-10 15:56:56 +00:00
write_log(" ================== vulkan layer destroy instance ==================");
2023-01-11 17:51:31 +00:00
unsafe {
let destroy_instance: PFN_vkDestroyInstance =
mem::transmute(vk_handles().handle("vkDestroyInstance").unwrap());
destroy_instance(instance, allocator);
}
2023-01-10 13:24:04 +00:00
}
extern "system" fn create_device(
physical_device: VkPhysicalDevice,
create_info: *const VkDeviceCreateInfo<'_>,
allocator: *const VkAllocationCallbacks,
device: *mut VkDevice,
) -> VkResult {
2023-01-10 15:56:56 +00:00
write_log(" ================== vulkan layer create device ==================");
2023-01-10 13:24:04 +00:00
2023-01-10 17:20:18 +00:00
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;
}
};
2023-01-11 14:03:32 +00:00
let proc_addr = chain_info.layer_info().next_device_proc_addr;
chain_info.advance_layer_info();
2023-01-10 17:20:18 +00:00
let result = unsafe {
2023-01-11 14:03:32 +00:00
let create_device: PFN_vkCreateDevice =
mem::transmute(vk_handles().handle("vkCreateDevice").unwrap());
create_device(physical_device, create_info, allocator, device)
2023-01-10 17:20:18 +00:00
};
if result != VK_SUCCESS {
return result;
}
2023-01-11 14:03:32 +00:00
vk_handles_mut().load_device_functions(unsafe { *device }, proc_addr);
2023-01-12 08:17:24 +00:00
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;
}
},
);
}
2023-01-10 17:20:18 +00:00
2023-01-10 13:24:04 +00:00
VK_SUCCESS
}
extern "system" fn destroy_device(device: VkDevice, allocator: *const VkAllocationCallbacks) {
2023-01-10 15:56:56 +00:00
write_log(" ================== vulkan layer destroy device ==================");
2023-01-11 17:51:31 +00:00
unsafe {
let destroy_device: PFN_vkDestroyDevice =
mem::transmute(vk_handles().handle("vkDestroyDevice").unwrap());
destroy_device(device, allocator);
}
2023-01-10 13:24:04 +00:00
}
2023-01-12 08:17:24 +00:00
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) }
}
2023-01-11 17:51:31 +00:00
pub fn write_log(msg: impl ToString) {
2023-01-10 13:24:04 +00:00
let mut file = OpenOptions::new()
.append(true)
.create(true)
2023-01-10 18:33:45 +00:00
.open(LOG_FILE)
2023-01-10 13:24:04 +00:00
.unwrap();
file.write_all(format!("{}\n", msg.to_string()).as_bytes())
.unwrap();
}
2023-01-12 08:17:24 +00:00
pub fn get_vk_func(s: &str) -> Option<Functions> {
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,
}
}