diff --git a/Cargo.toml b/Cargo.toml index 9d10dea..cf5a4ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ paste = "1.0.14" serde = "1.0.192" serde_json = "1.0.108" ringbuf = "0.3.3" +lazy_static = "1.4.0" [profile.release-lto] inherits = "release" diff --git a/src/lib.rs b/src/lib.rs index 74ac621..234447d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,13 +5,39 @@ use std::{ fs::{self, File, OpenOptions}, io::Write, path::Path, + sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}, }; +use lazy_static::lazy_static; use overlay::{Overlay, OverlayConfig}; static mut LOG_ENABLED: bool = true; static mut LOG_FILE: String = String::new(); -static mut OVERLAY: Overlay = Overlay::new(); +lazy_static! { + static ref OVERLAY: RwLock = RwLock::new(Overlay::new()); +} + +pub(crate) fn overlay() -> RwLockReadGuard<'static, Overlay> { + match OVERLAY.try_read() { + Ok(overlay) => overlay, + Err(_) => { + write_log!("failed to get read handle from OVERLAY"); + write_log!(std::backtrace::Backtrace::force_capture()); + panic!(); + } + } +} + +pub(crate) fn overlay_mut() -> RwLockWriteGuard<'static, Overlay> { + match OVERLAY.try_write() { + Ok(overlay) => overlay, + Err(_) => { + write_log!("failed to get write handle from OVERLAY"); + write_log!(std::backtrace::Backtrace::force_capture()); + panic!(); + } + } +} pub(crate) fn logging() -> bool { unsafe { LOG_ENABLED } @@ -96,7 +122,11 @@ pub fn check_logging(home: &str) { LOG_FILE = format!("{}/rf2_vk_hud.log", home); } - if let Err(_) = File::create(unsafe { &LOG_FILE }) {} + if let Err(_) = OpenOptions::new() + .append(true) + .create(true) + .open(unsafe { &LOG_FILE }) + {} write_log!(" =================================================================="); write_log!(" ======================= New Negotiation =========================="); diff --git a/src/overlay/mod.rs b/src/overlay/mod.rs index e11e641..15b0dfa 100644 --- a/src/overlay/mod.rs +++ b/src/overlay/mod.rs @@ -12,8 +12,7 @@ mod rfactor_data; use anyhow::Result; use assetpath::AssetPath; use std::{ - cell::RefCell, - rc::Rc, + collections::HashMap, sync::{Arc, Mutex}, }; use ui::{guihandler::guihandler::Font, prelude::*}; @@ -62,28 +61,38 @@ impl OverlayConfig { } } +#[derive(Debug)] +pub struct InstanceCollection { + pub instance: Arc, + pub physical_devices: Vec, + pub device_collection: HashMap, +} + +#[derive(Debug)] +pub struct DeviceCollection { + pub device: Arc, + pub queues: HashMap>>, + pub swapchains: HashMap>, +} + pub struct Overlay { config: OverlayConfig, - instance: Option>, - device: Option>, - queue: Option>>, + pub(crate) instances: HashMap, rendering: Option, gui_handler: Option>, - ui_elements: Vec>>, + ui_elements: Vec>>, rfactor_data: Option, } impl Overlay { - pub const fn new() -> Self { + pub fn new() -> Self { Self { config: OverlayConfig::new(), - instance: None, - device: None, - queue: None, + instances: HashMap::new(), rendering: None, gui_handler: None, ui_elements: Vec::new(), @@ -96,28 +105,132 @@ impl Overlay { self.config = config; } - pub fn set_instance(&mut self, instance: Arc) { - self.instance = Some(instance); + pub fn add_instance(&mut self, instance: Arc) { + let physical_devices = match instance.enumerate_physical_devices() { + Ok(devices) => devices, + Err(err) => { + write_log!(format!("failed to enumerate physical devices {err:?}")); + panic!(); + } + }; + + self.instances.insert( + instance.vk_handle(), + InstanceCollection { + instance, + physical_devices, + device_collection: HashMap::new(), + }, + ); } - pub fn instance(&self) -> Arc { - self.instance.as_ref().unwrap().clone() + pub fn remove_instance(&mut self, handle: VkInstance) { + self.instances.remove(&handle); + } + + pub fn instance_by_physical_device(&self, physical_device: VkPhysicalDevice) -> Arc { + match self + .instances + .values() + .find(|collection| { + collection + .physical_devices + .iter() + .find(|&&phys_dev| phys_dev == physical_device) + .is_some() + }) + .map(|collection| &collection.instance) + { + Some(instance) => instance.clone(), + None => { + write_log!(format!( + "failed to find instance with physical device ({physical_device:?})" + )); + panic!(); + } + } } pub fn set_device(&mut self, device: Arc) { - self.device = Some(device); + if let Some(instance_collection) = self + .instances + .get_mut(&device.physical_device().instance().vk_handle()) + { + instance_collection.device_collection.insert( + device.vk_handle(), + DeviceCollection { + device, + queues: HashMap::new(), + swapchains: HashMap::new(), + }, + ); + } } - pub fn device(&self) -> Arc { - self.device.as_ref().unwrap().clone() + fn device_collection(&self, device: VkDevice) -> &DeviceCollection { + for instance_collection in self.instances.values() { + if let Some(device_collection) = instance_collection.device_collection.get(&device) { + return device_collection; + } + } + + write_log!(format!("device ({device:?}) not found")); + panic!(); + } + + fn device_collection_mut(&mut self, device: &Arc) -> &mut DeviceCollection { + if let Some(instance_collection) = self + .instances + .get_mut(&device.physical_device().instance().vk_handle()) + { + if let Some(device_collection) = instance_collection + .device_collection + .get_mut(&device.vk_handle()) + { + return device_collection; + } + } + + write_log!(format!("device ({device:?}) not found")); + panic!(); + } + + pub fn device(&self, handle: VkDevice) -> Arc { + self.device_collection(handle).device.clone() } pub fn set_queue(&mut self, queue: Arc>) { - self.queue = Some(queue); + let handle = queue.lock().unwrap().vk_handle(); + let device = queue.lock().unwrap().device().clone(); + + self.device_collection_mut(&device) + .queues + .insert(handle, queue); } - pub fn queue(&self) -> Arc> { - self.queue.as_ref().unwrap().clone() + pub fn queue(&self, device: VkDevice, queue: VkQueue) -> Arc> { + match self.device_collection(device).queues.get(&queue) { + Some(queue) => queue.clone(), + None => { + write_log!(format!("queue ({queue:?} not found)")); + panic!(); + } + } + } + + pub fn device_queue(&self, device: VkDevice) -> Arc> { + self.device_collection(device) + .queues + .values() + .next() + .expect(&format!("no queue for device ({device:?}) present")) + .clone() + } + + pub fn insert_swapchain(&mut self, swapchain: Arc) { + self.device_collection_mut(swapchain.device()) + .swapchains + .insert(swapchain.vk_handle(), swapchain); } pub fn swapchain(&self, swapchain: VkSwapchainKHR) -> Option<&Arc> { @@ -130,14 +243,32 @@ impl Overlay { } } - pub fn create_rendering(&mut self, swapchain: Arc) -> Result<()> { + pub fn create_rendering(&mut self, device: VkDevice) -> Result<()> { write_log!("-> create rendering: start"); self.rendering = None; write_log!("-> create rendering: old cleared"); - let mut rendering = Rendering::new(self.queue(), swapchain.clone())?; + let device_collection = self.device_collection(device); + + let device = &device_collection.device.clone(); + let queue = match device_collection.queues.values().next() { + Some(queue) => queue.clone(), + None => { + write_log!(format!("failed to find queue")); + panic!(); + } + }; + let swapchain = match device_collection.swapchains.values().next() { + Some(swapchain) => swapchain.clone(), + None => { + write_log!(format!("failed to find swapchain")); + panic!(); + } + }; + + let mut rendering = Rendering::new(queue.clone(), swapchain.clone())?; write_log!("-> create rendering: new created"); @@ -152,78 +283,80 @@ impl Overlay { // provide trait required by GuiHandler let ctx = Arc::new(ContextImpl::new( - self.device(), - self.queue(), - swapchain, + device.clone(), + queue.clone(), + swapchain.clone(), rendering.images().clone(), )); + write_log!("create rendering: context created"); + // create GuiHandler let gui_handler = GuiHandler::new(create_info, &(ctx as Arc))?; - write_log!("GuiHandler successfully created"); + write_log!("create rendering: GuiHandler successfully created"); // create ui elements // create watermark if self.config.ui_config.enable_watermark { - let watermark = Rc::new(RefCell::new(Watermark::new(&gui_handler)?)); + let watermark = Arc::new(Mutex::new(Watermark::new(&gui_handler)?)); self.ui_elements.push(watermark); - write_log!("Watermark successfully created"); + write_log!("create rendering: Watermark successfully created"); } // create radar if self.config.ui_config.enable_radar { - let radar = Rc::new(RefCell::new(Radar::new( + let radar = Arc::new(Mutex::new(Radar::new( self.config.radar_config, - self.device(), - self.queue(), + device.clone(), + queue.clone(), &rendering, )?)); rendering.add_render_callback({ let radar = radar.clone(); - move |index| radar.borrow().render(index) + move |index| radar.lock().unwrap().render(index) }); self.ui_elements.push(radar); - write_log!("Radar successfully created"); + write_log!("create rendering: Radar successfully created"); } // create pedals if self.config.ui_config.enable_pedals { - let pedals = Rc::new(RefCell::new(Pedals::new( + let pedals = Arc::new(Mutex::new(Pedals::new( &gui_handler, - self.device(), - self.queue(), + device.clone(), + queue.clone(), )?)); self.ui_elements.push(pedals.clone()); - rendering.add_render_callback(move |_| pedals.borrow().render()); + rendering.add_render_callback(move |_| pedals.lock().unwrap().render()); - write_log!("Pedals successfully created"); + write_log!("create rendering: Pedals successfully created"); } // create leaderboard if self.config.ui_config.enable_leaderboard { - let leaderboard = Rc::new(RefCell::new(LeaderBoard::new( + let leaderboard = Arc::new(Mutex::new(LeaderBoard::new( &gui_handler, self.config.leader_board_config, )?)); self.ui_elements.push(leaderboard); - write_log!("Leader Board successfully created"); + write_log!("create rendering: Leader Board successfully created"); } // add rendering callbacks rendering.add_render_callback({ let gui_handler = gui_handler.clone(); - let device = self.device(); - let queue = self.queue(); + let device = device.clone(); + let queue = queue.clone(); move |index| { let command_buffer = @@ -242,7 +375,7 @@ impl Overlay { } }); - write_log!("render callbacks added"); + write_log!("create rendering: render callbacks added"); self.rendering = Some(rendering); self.gui_handler = Some(gui_handler); diff --git a/src/overlay/rendering.rs b/src/overlay/rendering.rs index 5f5c33c..1a99ac4 100644 --- a/src/overlay/rendering.rs +++ b/src/overlay/rendering.rs @@ -14,7 +14,7 @@ pub struct Rendering { queue: Arc>, - render_callbacks: Vec Result>>>, + render_callbacks: Vec Result> + Send + Sync>>, } impl Rendering { @@ -60,7 +60,7 @@ impl Rendering { pub fn add_render_callback(&mut self, f: F) where - F: Fn(u32) -> Result> + 'static, + F: Fn(u32) -> Result> + Send + Sync + 'static, { self.render_callbacks.push(Box::new(f)); } diff --git a/src/overlay/rfactor_data.rs b/src/overlay/rfactor_data.rs index c542c3b..952af24 100644 --- a/src/overlay/rfactor_data.rs +++ b/src/overlay/rfactor_data.rs @@ -2,8 +2,7 @@ use anyhow::Result; use rfactor_sm_reader::*; use std::{ - cell::RefCell, - rc::Rc, + sync::{Arc, Mutex}, time::{Duration, Instant}, }; @@ -11,7 +10,7 @@ use crate::write_log; use super::UiOverlay; -pub trait DataReceiver { +pub trait DataReceiver: Send + Sync { fn game_phase_change(&mut self, phase: GamePhase) -> Result<()>; fn update_for_phase(&self, phase: GamePhase) -> bool; @@ -67,7 +66,7 @@ pub struct RFactorData { player_id: Option, previous_game_phase: GamePhase, - receivers: Vec>>, + receivers: Vec>>, } impl RFactorData { @@ -89,7 +88,7 @@ impl RFactorData { }) } - pub fn add_receiver(&mut self, receiver: Rc>) { + pub fn add_receiver(&mut self, receiver: Arc>) { self.receivers.push(receiver); } @@ -131,7 +130,8 @@ impl RFactorData { for receiver in self.receivers.iter() { receiver - .borrow_mut() + .lock() + .unwrap() .game_phase_change(self.previous_game_phase)?; } } @@ -140,7 +140,7 @@ impl RFactorData { } for receiver in self.receivers.iter() { - let mut rec_mut = receiver.borrow_mut(); + let mut rec_mut = receiver.lock().unwrap(); if rec_mut.update_for_phase(self.previous_game_phase) { rec_mut.scoring_update(self.previous_game_phase, &vehicle_scorings)?; @@ -156,7 +156,8 @@ impl RFactorData { for receiver in self.receivers.iter() { receiver - .borrow_mut() + .lock() + .unwrap() .game_phase_change(self.previous_game_phase)?; } } @@ -170,7 +171,7 @@ impl RFactorData { write_log!("new telemetry update"); for receiver in self.receivers.iter() { - let mut rec_mut = receiver.borrow_mut(); + let mut rec_mut = receiver.lock().unwrap(); if rec_mut.update_for_phase(self.previous_game_phase) { rec_mut.telemetry_update(self.player_id, &telemetries)?; diff --git a/src/vk_layer/mod.rs b/src/vk_layer/mod.rs index 7227bf8..405f7da 100644 --- a/src/vk_layer/mod.rs +++ b/src/vk_layer/mod.rs @@ -13,7 +13,7 @@ use std::{ffi::c_void, mem, os::raw::c_char, ptr}; static mut ACQUIRE_NEXT_IMAGE: PFN_vkAcquireNextImageKHR = unsafe { mem::transmute(vkVoidFunction as *const c_void) }; -use crate::{get_config, logging, write_log, OVERLAY}; +use crate::{get_config, logging, overlay, overlay_mut, write_log}; #[no_mangle] #[allow(non_snake_case)] @@ -24,9 +24,7 @@ pub(crate) extern "C" fn vkNegotiateLoaderLayerInterfaceVersion( check_logging(&home); - unsafe { - OVERLAY.set_config(get_config(&home)); - } + overlay_mut().set_config(get_config(&home)); unsafe { *pVersionStruct = VkNegotiateLayerInterface { @@ -202,7 +200,7 @@ pub(crate) extern "system" fn create_instance( } }; - OVERLAY.set_instance(ins); + overlay_mut().add_instance(ins); } write_log!("-> created local instance handle"); @@ -222,6 +220,7 @@ pub(crate) extern "system" fn destroy_instance( unsafe { if let Some(vk_fn) = vk_handles().handle("vkDestroyInstance") { let destroy_instance: PFN_vkDestroyInstance = mem::transmute(vk_fn); + overlay_mut().remove_instance(instance); destroy_instance(instance, allocator); } @@ -278,7 +277,9 @@ pub(crate) extern "system" fn create_device( }; }; - let pdev = match PhysicalDevice::from_raw(unsafe { OVERLAY.instance() }, physical_device) { + let instance = overlay().instance_by_physical_device(physical_device); + + let pdev = match PhysicalDevice::from_raw(instance, physical_device) { Ok(pdev) => pdev, Err(err) => { write_log!(format!("failed creating physical device: {:?}", err)); @@ -332,10 +333,8 @@ pub(crate) extern "system" fn create_device( write_log!("got queue from device"); - unsafe { - OVERLAY.set_device(device); - OVERLAY.set_queue(queue); - } + overlay_mut().set_device(device.clone()); + overlay_mut().set_queue(queue); VK_SUCCESS } @@ -378,11 +377,42 @@ pub(crate) extern "system" fn create_swapchain( *p_swapchain })); - let swapchain = unsafe { Swapchain::from_raw(OVERLAY.device(), &*create_info, *p_swapchain) }; + overlay_mut().insert_swapchain(unsafe { + Swapchain::from_raw(overlay().device(_device), &*create_info, *p_swapchain) + }); + + { + let instances = &overlay().instances; + + write_log!(format!("number of instances: {}", instances.len())); + + for instance_collection in instances.values() { + write_log!(format!( + "\tnumber of physical devices: {}", + instance_collection.physical_devices.len() + )); + + write_log!(format!( + "\tnumber of devices: {}", + instance_collection.device_collection.len() + )); + + for device_collection in instance_collection.device_collection.values() { + write_log!(format!( + "\t\tnumber of queues: {}", + device_collection.queues.len() + )); + write_log!(format!( + "\t\tnumber of swapchains: {}", + device_collection.swapchains.len() + )); + } + } + } write_log!("-> created Arc"); - if let Err(err) = unsafe { OVERLAY.create_rendering(swapchain) } { + if let Err(err) = overlay_mut().create_rendering(_device) { write_log!(format!("create overlay rendering struct failed: {:?}", err)); return VK_ERROR_INITIALIZATION_FAILED; } @@ -400,84 +430,96 @@ pub(crate) extern "system" fn acquire_next_image( fence: VkFence, image_index: *mut u32, ) -> VkResult { - unsafe { - match OVERLAY.swapchain(swapchain) { - Some(sc) => { - let device = OVERLAY.device(); + // 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), - ); + // let res = device.acquire_next_image( + // sc.vk_handle(), + // timeout, + // Some(semaphore), + // Some(fence), + // ); - write_log!(format!( - "acquire (swapchain: {:?}) res: {:?}", - sc.vk_handle(), - res - )); + // write_log!(format!( + // "acquire (swapchain: {:?}) res: {:?}", + // sc.vk_handle(), + // res + // )); - 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) => { - write_log!(format!("failed acquiring next image {:?}", err)); - VK_ERROR_DEVICE_LOST - } - } - } - None => { - write_log!("acquired other swapchain image"); - ACQUIRE_NEXT_IMAGE(device, swapchain, timeout, semaphore, fence, image_index) - } - } + // match res { + // Ok(res) => match res { + // OutOfDate::Ok(index) => { + // sc.set_image_index(index); + // *image_index = index; + // VK_SUCCESS + // } + // OutOfDate::OutOfDate => VK_ERROR_OUT_OF_DATE_KHR, + // OutOfDate::TimeOut => VK_TIMEOUT, + // }, + // Err(err) => { + // write_log!(format!("failed acquiring next image {:?}", err)); + // VK_ERROR_DEVICE_LOST + // } + // } + // } + // None => { + // write_log!("acquired other swapchain image"); + // ACQUIRE_NEXT_IMAGE(device, swapchain, timeout, semaphore, fence, image_index) + // } + // } + // } + + let res = + unsafe { ACQUIRE_NEXT_IMAGE(device, swapchain, timeout, semaphore, fence, image_index) }; + + if res != VK_SUCCESS { + write_log!(" ================== vulkan layer acquire next image =================="); + write_log!(format!("image index: {}", unsafe { *image_index })); + write_log!(format!("result: {:?}", VkResult::from(res))); } + + res } pub(crate) extern "system" fn present_queue( queue: VkQueue, present_info: *const VkPresentInfoKHR, ) -> VkResult { - 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, - ); + // 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, + // ); - write_log!(format!("present {} swapchain(s)", swapchains.len())); + // write_log!(format!("present {} swapchain(s)", swapchains.len())); - for swapchain in swapchains { - write_log!(format!("present swapchain: {:?}", swapchain)); + // for swapchain in swapchains { + // write_log!(format!("present swapchain: {:?}", swapchain)); - if let Some(swch) = OVERLAY.swapchain(*swapchain) { - write_log!(format!( - " -> internal swapchain found! ({:?})", - swch.vk_handle() - )); - } - } - } - } + // if let Some(swch) = OVERLAY.swapchain(*swapchain) { + // write_log!(format!( + // " -> internal swapchain found! ({:?})", + // swch.vk_handle() + // )); + // } + // } + // } + // } - match unsafe { OVERLAY.render() } { - Ok(_) => (), - Err(err) => { - write_log!(format!("overlay rendering failed: {:?}", err)); - return VK_ERROR_DEVICE_LOST; - } - }; + // match unsafe { OVERLAY.render() } { + // Ok(_) => (), + // Err(err) => { + // write_log!(format!("overlay rendering failed: {:?}", err)); + // return VK_ERROR_DEVICE_LOST; + // } + // }; let pfn: PFN_vkQueuePresentKHR = match vk_handles().handle("vkQueuePresentKHR") { Some(pfn) => unsafe { mem::transmute(pfn) }, @@ -487,5 +529,11 @@ pub(crate) extern "system" fn present_queue( } }; - pfn(queue, present_info) + let res = pfn(queue, present_info); + + if res != VK_SUCCESS { + write_log!(format!("queue present failed: {:?}", VkResult::from(res))); + } + + res }