rFactor2_vk_hud/src/lib.rs

551 lines
16 KiB
Rust
Raw Normal View History

2023-01-10 13:24:04 +00:00
pub mod enums;
pub mod structs;
2023-01-12 09:10:09 +00:00
mod overlay;
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-16 16:07:39 +00:00
fs::{self, File, OpenOptions},
2023-01-10 18:33:45 +00:00
io::Write,
mem,
os::raw::c_char,
2023-01-16 16:07:39 +00:00
path::Path,
2023-01-14 07:08:40 +00:00
ptr,
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::*;
2023-01-16 16:07:39 +00:00
use overlay::{Overlay, OverlayConfig};
2023-01-10 13:24:04 +00:00
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-14 19:15:43 +00:00
static mut LOG_ENABLED: bool = true;
2023-01-14 07:08:40 +00:00
static mut LOG_FILE: String = String::new();
2023-01-12 09:10:09 +00:00
static mut OVERLAY: Overlay = Overlay::new();
2023-01-13 14:00:01 +00:00
static mut ACQUIRE_NEXT_IMAGE: PFN_vkAcquireNextImageKHR =
unsafe { mem::transmute(vkVoidFunction as *const c_void) };
2023-01-12 08:17:24 +00:00
2023-01-14 19:15:43 +00:00
pub(crate) fn logging() -> bool {
unsafe { LOG_ENABLED }
}
macro_rules! write_log {
($msg:expr) => {
if crate::logging() {
crate::log($msg);
}
};
}
pub(crate) use write_log;
2023-01-10 13:24:04 +00:00
#[no_mangle]
#[allow(non_snake_case)]
2023-01-14 07:08:40 +00:00
pub(crate) extern "C" fn vkNegotiateLoaderLayerInterfaceVersion(
2023-01-10 13:24:04 +00:00
pVersionStruct: *mut VkNegotiateLayerInterface,
) -> VkResult {
2023-01-14 19:15:43 +00:00
let log_enabled = match std::env::var("RFACTOR_HUD_LOG") {
Ok(var) => {
let i: u32 = var.parse().unwrap_or(0);
i == 1
}
Err(_) => false,
};
2023-01-14 07:08:40 +00:00
2023-01-14 19:15:43 +00:00
unsafe { LOG_ENABLED = log_enabled };
2023-01-10 18:33:45 +00:00
2023-01-16 16:07:39 +00:00
let home = std::env::var("HOME").unwrap();
2023-01-14 19:15:43 +00:00
if logging() {
unsafe {
LOG_FILE = format!("{}/rf2_vk_hud.log", home);
}
if let Err(_) = File::create(unsafe { &LOG_FILE }) {}
write_log!(" ==================================================================");
write_log!(" ======================= New Negotiation ==========================");
write_log!(" ==================================================================");
}
2023-01-10 13:24:04 +00:00
2023-01-16 16:07:39 +00:00
let config_path = Path::new(&home).join(".config/rFactorHUD/config.json");
let config = if config_path.exists() {
fs::read_to_string(&config_path)
.map(|s| {
serde_json::from_str(&s).unwrap_or({
write_log!("failed to deserialize config file");
OverlayConfig::new()
})
})
.unwrap_or({
write_log!(format!("failed to open config file: {:?}", config_path));
OverlayConfig::new()
})
} else {
if let Err(err) = std::fs::create_dir_all(config_path.parent().unwrap()) {
write_log!(format!("failed to create dirs for config file: {:?}", err));
}
let config = OverlayConfig::new();
match File::create(config_path) {
Ok(mut file) => match serde_json::to_string(&config) {
Ok(conf_str) => {
if let Err(err) = file.write_all(conf_str.as_bytes()) {
write_log!(format!("failed to write to config file: {:?}", err));
}
}
Err(err) => {
write_log!(format!("failed to serialize config: {:?}", err));
}
},
Err(err) => {
write_log!(format!("failed to create config file: {:?}", err));
}
}
config
};
unsafe {
OVERLAY.set_config(config);
}
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-12 09:10:09 +00:00
set_vk_handles(match VkTypedefHandles::new() {
Ok(handles) => handles,
Err(err) => {
2023-01-14 19:15:43 +00:00
write_log!(format!("failed to load typedef handles {:?}", err));
2023-01-12 09:10:09 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
});
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(_) => {
2023-01-14 19:15:43 +00:00
write_log!("Err: failed creating string");
2023-01-10 13:24:04 +00:00
return Functions::Null.convert();
}
};
2023-01-10 15:56:56 +00:00
let s = func_string.as_str();
2023-01-13 08:27:58 +00:00
if let Some(func) = Functions::get_vk_func(s) {
2023-01-12 08:17:24 +00:00
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-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(_) => {
2023-01-14 19:15:43 +00:00
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-13 08:27:58 +00:00
if let Some(func) = Functions::get_vk_func(s) {
2023-01-12 08:17:24 +00:00
return func.convert();
}
2023-01-11 17:51:31 +00:00
if let Some(func) = vk_handles().handle(s) {
return func;
}
Functions::Null.convert()
2023-01-11 05:00:35 +00:00
}
2023-01-14 07:08:40 +00:00
pub(crate) extern "system" fn create_instance(
2023-01-10 13:24:04 +00:00
create_info: *const VkInstanceCreateInfo,
allocator: *const VkAllocationCallbacks,
instance: *mut VkInstance,
) -> VkResult {
2023-01-14 19:15:43 +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-14 19:15:43 +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
2023-01-14 19:15:43 +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() };
2023-01-14 19:15:43 +00:00
write_log!(format!("{:?}", ext_names));
2023-01-12 08:17:24 +00:00
// 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) => {
2023-01-14 19:15:43 +00:00
write_log!(format!("-> local instance creation failed: {:?}", err));
2023-01-12 08:17:24 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
};
2023-01-12 09:10:09 +00:00
OVERLAY.set_instance(ins);
2023-01-12 08:17:24 +00:00
}
2023-01-14 19:15:43 +00:00
write_log!("-> created local instance handle");
2023-01-12 08:17:24 +00:00
}
2023-01-10 13:24:04 +00:00
VK_SUCCESS
}
2023-01-14 07:08:40 +00:00
pub(crate) extern "system" fn destroy_instance(
2023-01-13 08:27:58 +00:00
instance: VkInstance,
allocator: *const VkAllocationCallbacks,
) {
2023-01-14 19:15:43 +00:00
write_log!(" ================== vulkan layer destroy instance ==================");
2023-01-11 17:51:31 +00:00
unsafe {
2023-01-12 09:10:09 +00:00
if let Some(vk_fn) = vk_handles().handle("vkDestroyInstance") {
let destroy_instance: PFN_vkDestroyInstance = mem::transmute(vk_fn);
2023-01-11 17:51:31 +00:00
2023-01-12 09:10:09 +00:00
destroy_instance(instance, allocator);
}
2023-01-11 17:51:31 +00:00
}
2023-01-10 13:24:04 +00:00
}
2023-01-14 07:08:40 +00:00
pub(crate) extern "system" fn create_device(
2023-01-10 13:24:04 +00:00
physical_device: VkPhysicalDevice,
create_info: *const VkDeviceCreateInfo<'_>,
allocator: *const VkAllocationCallbacks,
device: *mut VkDevice,
) -> VkResult {
2023-01-14 19:15:43 +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 => {
2023-01-14 19:15:43 +00:00
write_log!("device chain info not found.");
2023-01-10 17:20:18 +00:00
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-12 09:10:09 +00:00
match vk_handles().handle("vkCreateDevice") {
Some(vk_fn) => {
let create_device: PFN_vkCreateDevice = mem::transmute(vk_fn);
create_device(physical_device, create_info, allocator, device)
}
None => {
2023-01-14 19:15:43 +00:00
write_log!("failed creating device");
2023-01-12 09:10:09 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
}
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 09:10:09 +00:00
unsafe {
2023-01-13 14:00:01 +00:00
ACQUIRE_NEXT_IMAGE = match vk_handles().handle("vkAcquireNextImageKHR") {
Some(acquire_next_image) => mem::transmute(acquire_next_image),
None => {
2023-01-14 19:15:43 +00:00
write_log!("failed querying vkAcquireNextImageKHR");
2023-01-13 14:00:01 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
};
2023-01-12 09:10:09 +00:00
};
2023-01-12 08:17:24 +00:00
2023-01-12 09:10:09 +00:00
let pdev = match PhysicalDevice::from_raw(unsafe { OVERLAY.instance() }, physical_device) {
Ok(pdev) => pdev,
Err(err) => {
2023-01-14 19:15:43 +00:00
write_log!(format!("failed creating physical device: {:?}", err));
2023-01-12 09:10:09 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
};
2023-01-14 07:08:40 +00:00
let queue_info = match Queue::create_non_presentable_request_info(&pdev, VK_QUEUE_GRAPHICS_BIT)
{
Ok(qi) => qi,
Err(err) => {
2023-01-14 19:15:43 +00:00
write_log!(format!("failed getting queue info: {:?}", err));
2023-01-14 07:08:40 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
};
unsafe {
let create_queue_info = std::slice::from_raw_parts(
(*create_info).pQueueCreateInfos,
(*create_info).queueCreateInfoCount as usize,
);
for info in create_queue_info {
2023-01-14 19:15:43 +00:00
write_log!(format!(
2023-01-14 07:08:40 +00:00
"pCreateDeviceInfo; queue fam: {}, queue count: {}",
info.queueFamilyIndex, info.queueCount
));
}
2023-01-14 19:15:43 +00:00
write_log!(format!(
2023-01-14 07:08:40 +00:00
"Queue: queue fam: {}, queue count: {}",
queue_info.queue_create_info.queueFamilyIndex, queue_info.queue_create_info.queueCount
));
}
2023-01-12 08:17:24 +00:00
let ext_names = unsafe { (*create_info).extension_names() };
2023-01-14 19:15:43 +00:00
write_log!(format!("{:?}", ext_names));
2023-01-12 08:17:24 +00:00
2023-01-14 07:08:40 +00:00
let device = match Device::preinitialized(unsafe { *device }, proc_addr, pdev, &ext_names) {
Ok(dev) => dev,
Err(err) => {
2023-01-14 19:15:43 +00:00
write_log!(format!("-> local device creation failed: {:?}", err));
2023-01-14 07:08:40 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
};
2023-01-14 19:15:43 +00:00
write_log!("created device");
2023-01-14 07:08:40 +00:00
let queue = device.get_queue(queue_info.queue_family_index, queue_info.queue_index);
2023-01-14 19:15:43 +00:00
write_log!("got queue from device");
2023-01-14 07:08:40 +00:00
2023-01-12 08:17:24 +00:00
unsafe {
2023-01-14 07:08:40 +00:00
OVERLAY.set_device(device);
OVERLAY.set_queue(queue);
2023-01-12 08:17:24 +00:00
}
2023-01-10 17:20:18 +00:00
2023-01-10 13:24:04 +00:00
VK_SUCCESS
}
2023-01-14 07:08:40 +00:00
pub(crate) extern "system" fn destroy_device(
device: VkDevice,
allocator: *const VkAllocationCallbacks,
) {
2023-01-14 19:15:43 +00:00
write_log!(" ================== vulkan layer destroy device ==================");
2023-01-11 17:51:31 +00:00
unsafe {
2023-01-12 09:10:09 +00:00
if let Some(vk_fn) = vk_handles().handle("vkDestroyDevice") {
let destroy_device: PFN_vkDestroyDevice = mem::transmute(vk_fn);
2023-01-11 17:51:31 +00:00
2023-01-12 09:10:09 +00:00
destroy_device(device, allocator);
}
2023-01-11 17:51:31 +00:00
}
2023-01-10 13:24:04 +00:00
}
2023-01-14 07:08:40 +00:00
pub(crate) extern "system" fn create_swapchain(
2023-01-12 08:17:24 +00:00
_device: VkDevice,
create_info: *const VkSwapchainCreateInfoKHR,
_allocator: *const VkAllocationCallbacks,
p_swapchain: *mut VkSwapchainKHR,
) -> VkResult {
2023-01-14 19:15:43 +00:00
write_log!(" ================== vulkan layer create swapchain ==================");
2023-01-12 08:17:24 +00:00
2023-01-12 12:52:44 +00:00
let create_swapchain: PFN_vkCreateSwapchainKHR =
match vk_handles().handle("vkCreateSwapchainKHR") {
Some(create_swapchain) => unsafe { mem::transmute(create_swapchain) },
None => {
2023-01-14 19:15:43 +00:00
write_log!("failed querying vkCreateSwapchainKHR");
2023-01-12 12:52:44 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
};
2023-01-12 08:17:24 +00:00
2023-01-12 12:52:44 +00:00
create_swapchain(_device, create_info, _allocator, p_swapchain);
2023-01-14 19:15:43 +00:00
write_log!(format!("-> created swapchain vk handle {:?}", unsafe {
2023-01-14 07:08:40 +00:00
*p_swapchain
}));
2023-01-12 16:45:06 +00:00
2023-01-12 12:52:44 +00:00
let swapchain =
match unsafe { Swapchain::from_raw(OVERLAY.device(), &*create_info, *p_swapchain) } {
Ok(swapchain) => swapchain,
Err(err) => {
2023-01-14 19:15:43 +00:00
write_log!(format!("create swapchain failed: {:?}", err));
2023-01-12 12:52:44 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
};
2023-01-14 19:15:43 +00:00
write_log!("-> created Arc<Swapchain>");
2023-01-12 16:45:06 +00:00
if let Err(err) = unsafe { OVERLAY.create_rendering(swapchain) } {
2023-01-14 19:15:43 +00:00
write_log!(format!("create overlay rendering struct failed: {:?}", err));
2023-01-12 16:45:06 +00:00
return VK_ERROR_INITIALIZATION_FAILED;
}
2023-01-14 19:15:43 +00:00
write_log!("-> created renderer");
2023-01-12 08:17:24 +00:00
VK_SUCCESS
}
2023-01-14 07:08:40 +00:00
pub(crate) extern "system" fn acquire_next_image(
2023-01-13 08:27:58 +00:00
device: VkDevice,
swapchain: VkSwapchainKHR,
timeout: u64,
semaphore: VkSemaphore,
fence: VkFence,
2023-01-13 14:00:01 +00:00
image_index: *mut u32,
2023-01-13 08:27:58 +00:00
) -> VkResult {
2023-01-13 14:00:01 +00:00
unsafe {
match OVERLAY.swapchain(swapchain) {
Some(sc) => {
let device = OVERLAY.device();
let res = device.acquire_next_image(
sc.vk_handle(),
timeout,
Some(semaphore),
Some(fence),
);
2023-01-14 19:15:43 +00:00
write_log!(format!(
2023-01-14 07:08:40 +00:00
"acquire (swapchain: {:?}) res: {:?}",
sc.vk_handle(),
res
));
2023-01-13 14:00:01 +00:00
match res {
Ok(res) => match res {
OutOfDate::Ok(index) => {
sc.set_image_index(index);
VK_SUCCESS
}
OutOfDate::OutOfDate => VK_ERROR_OUT_OF_DATE_KHR,
OutOfDate::TimeOut => VK_TIMEOUT,
},
Err(err) => {
2023-01-14 19:15:43 +00:00
write_log!(format!("failed acquiring next image {:?}", err));
2023-01-13 14:00:01 +00:00
VK_ERROR_DEVICE_LOST
}
}
}
None => {
2023-01-14 19:15:43 +00:00
write_log!("acquired other swapchain image");
2023-01-13 14:00:01 +00:00
ACQUIRE_NEXT_IMAGE(device, swapchain, timeout, semaphore, fence, image_index)
}
}
}
}
2023-01-14 07:08:40 +00:00
pub(crate) extern "system" fn present_queue(
2023-01-13 14:00:01 +00:00
queue: VkQueue,
present_info: *const VkPresentInfoKHR,
) -> VkResult {
2023-01-14 19:15:43 +00:00
if logging() {
write_log!(" ================== vulkan layer queue present ==================");
write_log!(format!("iq: {:?}, cq: {:?}", queue, unsafe {
OVERLAY.queue().lock().unwrap().vk_handle()
}));
unsafe {
let swapchains = std::slice::from_raw_parts(
(*present_info).pSwapchains,
(*present_info).swapchainCount as usize,
);
2023-01-14 07:08:40 +00:00
2023-01-14 19:15:43 +00:00
write_log!(format!("present {} swapchain(s)", swapchains.len()));
2023-01-14 07:08:40 +00:00
2023-01-14 19:15:43 +00:00
for swapchain in swapchains {
write_log!(format!("present swapchain: {:?}", swapchain));
2023-01-14 07:08:40 +00:00
2023-01-14 19:15:43 +00:00
if let Some(swch) = OVERLAY.swapchain(*swapchain) {
write_log!(format!(
" -> internal swapchain found! ({:?})",
swch.vk_handle()
));
}
2023-01-14 07:08:40 +00:00
}
}
}
match unsafe { OVERLAY.render() } {
Ok(_) => (),
Err(err) => {
2023-01-14 19:15:43 +00:00
write_log!(format!("overlay rendering failed: {:?}", err));
2023-01-14 07:08:40 +00:00
return VK_ERROR_DEVICE_LOST;
}
};
2023-01-13 14:00:01 +00:00
let pfn: PFN_vkQueuePresentKHR = match vk_handles().handle("vkQueuePresentKHR") {
Some(pfn) => unsafe { mem::transmute(pfn) },
None => {
2023-01-14 19:15:43 +00:00
write_log!("failed querying vkQueuePresentKHR");
2023-01-13 14:00:01 +00:00
return VK_ERROR_DEVICE_LOST;
}
};
pfn(queue, present_info)
2023-01-13 08:27:58 +00:00
}
2023-01-14 19:15:43 +00:00
pub fn log(msg: impl ToString) {
assert!(logging());
2023-01-14 07:08:40 +00:00
if let Ok(mut file) = OpenOptions::new()
.append(true)
.create(true)
.open(unsafe { &LOG_FILE })
{
2023-01-12 09:10:09 +00:00
if let Err(_) = file.write_all(format!("{}\n", msg.to_string()).as_bytes()) {}
}
2023-01-10 13:24:04 +00:00
}