From bd31f4fbb59955f035486140d8da8b1363734184 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Fri, 20 Jan 2023 05:49:57 +0100 Subject: [PATCH 01/12] Add proper reset function --- .../elements/leaderboard/leaderboard_entry.rs | 18 ++++++++++-------- src/overlay/elements/leaderboard/mod.rs | 8 ++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/overlay/elements/leaderboard/leaderboard_entry.rs b/src/overlay/elements/leaderboard/leaderboard_entry.rs index 6d5a9db..01bdf30 100644 --- a/src/overlay/elements/leaderboard/leaderboard_entry.rs +++ b/src/overlay/elements/leaderboard/leaderboard_entry.rs @@ -126,6 +126,14 @@ impl LeaderBoardEntry { self.place_label.set_text(self.place) } + pub fn reset_time(&mut self) -> Result<()> { + self.behind = BehindLeader::Time(f64::MIN); + self.best_lap = f64::MIN; + self.time_behind_next = f64::MIN; + + self.time_label.set_text("---") + } + pub fn update_time_behind_leader(&mut self, behind: BehindLeader) -> Result<()> { if self.behind != behind { self.behind = behind; @@ -149,13 +157,7 @@ impl LeaderBoardEntry { } } BehindLeader::Laps(laps_behind) => { - let text = if laps_behind == 1 { - format!("+{} Lap", laps_behind) - } else { - format!("+{} Laps", laps_behind) - }; - - self.time_label.set_text(text)?; + self.time_label.set_text(format!("+{}", laps_behind))?; } } } @@ -167,7 +169,7 @@ impl LeaderBoardEntry { if self.best_lap != time { self.best_lap = time; - if self.best_lap < 0.0 { + if self.best_lap <= 0.0 { self.time_label.set_text("---")?; } else { let text = if self.best_lap > 60.0 { diff --git a/src/overlay/elements/leaderboard/mod.rs b/src/overlay/elements/leaderboard/mod.rs index 075c9fb..141e3a6 100644 --- a/src/overlay/elements/leaderboard/mod.rs +++ b/src/overlay/elements/leaderboard/mod.rs @@ -276,7 +276,7 @@ impl DataReceiver for LeaderBoard { match phase { GamePhase::Practice | GamePhase::Qualifying | GamePhase::TestDay => { for entry in self.leaderboard_entries.iter_mut() { - entry.update_best_lap(-1.0)?; + entry.reset_time()?; } self.leaderboard.enable()?; @@ -284,7 +284,11 @@ impl DataReceiver for LeaderBoard { GamePhase::Race => { for entry in self.leaderboard_entries.iter_mut() { - entry.update_time_behind_leader(BehindLeader::Time(0.0))?; + entry.reset_time()?; + } + + for entry in self.deltaboard_entries.iter_mut() { + entry.reset_time()?; } self.leaderboard.enable()?; -- 2.45.2 From 8095d866c333cdbcb114f0768c39937263c875bf Mon Sep 17 00:00:00 2001 From: hodasemi Date: Fri, 20 Jan 2023 06:41:09 +0100 Subject: [PATCH 02/12] Move vk layer stuff into own directory --- src/lib.rs | 472 +------------------------------ src/{ => vk_layer}/enums.rs | 3 +- src/vk_layer/mod.rs | 472 +++++++++++++++++++++++++++++++ src/{ => vk_layer}/structs.rs | 2 +- src/{ => vk_layer}/vk_handles.rs | 2 +- 5 files changed, 477 insertions(+), 474 deletions(-) rename src/{ => vk_layer}/enums.rs (98%) create mode 100644 src/vk_layer/mod.rs rename src/{ => vk_layer}/structs.rs (99%) rename src/{ => vk_layer}/vk_handles.rs (97%) diff --git a/src/lib.rs b/src/lib.rs index 479f30b..57198a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,30 +1,17 @@ -pub mod enums; -pub mod structs; - mod overlay; -mod vk_handles; +mod vk_layer; use std::{ - ffi::c_void, fs::{self, File, OpenOptions}, io::Write, - mem, - os::raw::c_char, path::Path, - ptr, }; -use enums::*; use overlay::{Overlay, OverlayConfig}; -use structs::*; -use vk_handles::*; -use vulkan_rs::prelude::*; static mut LOG_ENABLED: bool = true; static mut LOG_FILE: String = String::new(); static mut OVERLAY: Overlay = Overlay::new(); -static mut ACQUIRE_NEXT_IMAGE: PFN_vkAcquireNextImageKHR = - unsafe { mem::transmute(vkVoidFunction as *const c_void) }; pub(crate) fn logging() -> bool { unsafe { LOG_ENABLED } @@ -82,463 +69,6 @@ fn get_config(home: &str) -> OverlayConfig { } } -#[no_mangle] -#[allow(non_snake_case)] -pub(crate) extern "C" fn vkNegotiateLoaderLayerInterfaceVersion( - pVersionStruct: *mut VkNegotiateLayerInterface, -) -> VkResult { - let log_enabled = match std::env::var("RFACTOR_HUD_LOG") { - Ok(var) => { - let i: u32 = var.parse().unwrap_or(0); - - i == 1 - } - Err(_) => false, - }; - - unsafe { LOG_ENABLED = log_enabled }; - - let home = std::env::var("HOME").unwrap(); - - 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!(" =================================================================="); - } - - unsafe { - OVERLAY.set_config(get_config(&home)); - } - - 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, - } - }; - - set_vk_handles(match VkTypedefHandles::new() { - Ok(handles) => handles, - Err(err) => { - write_log!(format!("failed to load typedef handles {:?}", err)); - return VK_ERROR_INITIALIZATION_FAILED; - } - }); - - VK_SUCCESS -} - -#[no_mangle] -extern "system" fn get_device_proc_addr( - _device: VkDevice, - 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(); - - if let Some(func) = Functions::get_vk_func(s) { - return func.convert(); - } - - if let Some(func) = vk_handles().handle(s) { - return func; - } - - Functions::Null.convert() -} - -#[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(); - } - }; - - let s = func_string.as_str(); - - if let Some(func) = Functions::get_vk_func(s) { - return func.convert(); - } - - if let Some(func) = vk_handles().handle(s) { - return func; - } - - Functions::Null.convert() -} - -pub(crate) 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!("instance chain info not found."); - return VK_ERROR_LAYER_NOT_PRESENT; - } - }; - - let proc_addr = chain_info.layer_info().next_instance_proc_addr; - let create_instance: PFN_vkCreateInstance = unsafe { - mem::transmute(proc_addr( - VkInstance::NULL_HANDLE, - VkString::new("vkCreateInstance").as_ptr(), - )) - }; - - chain_info.advance_layer_info(); - let result = create_instance(create_info, allocator, instance); - if result != VK_SUCCESS { - return result; - }; - - vk_handles_mut().load_instance_functions(unsafe { *instance }, proc_addr); - - 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; - } - }; - - OVERLAY.set_instance(ins); - } - - write_log!("-> created local instance handle"); - } - - VK_SUCCESS -} - -pub(crate) extern "system" fn destroy_instance( - instance: VkInstance, - allocator: *const VkAllocationCallbacks, -) { - write_log!(" ================== vulkan layer destroy instance =================="); - - unsafe { - if let Some(vk_fn) = vk_handles().handle("vkDestroyInstance") { - let destroy_instance: PFN_vkDestroyInstance = mem::transmute(vk_fn); - - destroy_instance(instance, allocator); - } - } -} - -pub(crate) 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 =================="); - - 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; - } - }; - - let proc_addr = chain_info.layer_info().next_device_proc_addr; - - chain_info.advance_layer_info(); - - let result = unsafe { - 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 => { - write_log!("failed creating device"); - return VK_ERROR_INITIALIZATION_FAILED; - } - } - }; - - if result != VK_SUCCESS { - return result; - } - - vk_handles_mut().load_device_functions(unsafe { *device }, proc_addr); - unsafe { - ACQUIRE_NEXT_IMAGE = match vk_handles().handle("vkAcquireNextImageKHR") { - Some(acquire_next_image) => mem::transmute(acquire_next_image), - None => { - write_log!("failed querying vkAcquireNextImageKHR"); - return VK_ERROR_INITIALIZATION_FAILED; - } - }; - }; - - let pdev = match PhysicalDevice::from_raw(unsafe { OVERLAY.instance() }, physical_device) { - Ok(pdev) => pdev, - Err(err) => { - write_log!(format!("failed creating physical device: {:?}", err)); - return VK_ERROR_INITIALIZATION_FAILED; - } - }; - - let queue_info = match Queue::create_non_presentable_request_info(&pdev, VK_QUEUE_GRAPHICS_BIT) - { - Ok(qi) => qi, - Err(err) => { - write_log!(format!("failed getting queue info: {:?}", err)); - 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 { - write_log!(format!( - "pCreateDeviceInfo; queue fam: {}, queue count: {}", - info.queueFamilyIndex, info.queueCount - )); - } - - write_log!(format!( - "Queue: queue fam: {}, queue count: {}", - queue_info.queue_create_info.queueFamilyIndex, queue_info.queue_create_info.queueCount - )); - } - - let ext_names = unsafe { (*create_info).extension_names() }; - - write_log!(format!("{:?}", ext_names)); - - let device = match Device::preinitialized(unsafe { *device }, proc_addr, pdev, &ext_names) { - Ok(dev) => dev, - Err(err) => { - write_log!(format!("-> local device creation failed: {:?}", err)); - return VK_ERROR_INITIALIZATION_FAILED; - } - }; - - write_log!("created device"); - - let queue = device.get_queue(queue_info.queue_family_index, queue_info.queue_index); - - write_log!("got queue from device"); - - unsafe { - OVERLAY.set_device(device); - OVERLAY.set_queue(queue); - } - - VK_SUCCESS -} - -pub(crate) extern "system" fn destroy_device( - device: VkDevice, - allocator: *const VkAllocationCallbacks, -) { - write_log!(" ================== vulkan layer destroy device =================="); - - unsafe { - if let Some(vk_fn) = vk_handles().handle("vkDestroyDevice") { - let destroy_device: PFN_vkDestroyDevice = mem::transmute(vk_fn); - - destroy_device(device, allocator); - } - } -} - -pub(crate) 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 create_swapchain: PFN_vkCreateSwapchainKHR = - match vk_handles().handle("vkCreateSwapchainKHR") { - Some(create_swapchain) => unsafe { mem::transmute(create_swapchain) }, - None => { - write_log!("failed querying vkCreateSwapchainKHR"); - return VK_ERROR_INITIALIZATION_FAILED; - } - }; - - create_swapchain(_device, create_info, _allocator, p_swapchain); - - write_log!(format!("-> created swapchain vk handle {:?}", unsafe { - *p_swapchain - })); - - let swapchain = - match unsafe { Swapchain::from_raw(OVERLAY.device(), &*create_info, *p_swapchain) } { - Ok(swapchain) => swapchain, - Err(err) => { - write_log!(format!("create swapchain failed: {:?}", err)); - return VK_ERROR_INITIALIZATION_FAILED; - } - }; - - write_log!("-> created Arc"); - - if let Err(err) = unsafe { OVERLAY.create_rendering(swapchain) } { - write_log!(format!("create overlay rendering struct failed: {:?}", err)); - return VK_ERROR_INITIALIZATION_FAILED; - } - - write_log!("-> created renderer"); - - VK_SUCCESS -} - -pub(crate) extern "system" fn acquire_next_image( - device: VkDevice, - swapchain: VkSwapchainKHR, - timeout: u64, - semaphore: VkSemaphore, - fence: VkFence, - image_index: *mut u32, -) -> VkResult { - 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), - ); - - 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) - } - } - } -} - -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, - ); - - write_log!(format!("present {} swapchain(s)", swapchains.len())); - - 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() - )); - } - } - } - } - - 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) }, - None => { - write_log!("failed querying vkQueuePresentKHR"); - return VK_ERROR_DEVICE_LOST; - } - }; - - pfn(queue, present_info) -} - pub fn log(msg: impl ToString) { assert!(logging()); diff --git a/src/enums.rs b/src/vk_layer/enums.rs similarity index 98% rename from src/enums.rs rename to src/vk_layer/enums.rs index 5f701e6..8e97d0e 100644 --- a/src/enums.rs +++ b/src/vk_layer/enums.rs @@ -3,7 +3,7 @@ use std::{mem, ptr}; use vulkan_rs::prelude::*; -use crate::*; +use super::*; pub use VkLayerFunction::*; pub use VkNegotiateLayerStructType::*; @@ -13,6 +13,7 @@ pub enum VkNegotiateLayerStructType { LAYER_NEGOTIATE_INTERFACE_STRUCT = 1, } +#[allow(unused)] #[derive(Clone, Copy, Eq, PartialEq)] pub enum VkLayerFunction { VK_LAYER_LINK_INFO = 0, diff --git a/src/vk_layer/mod.rs b/src/vk_layer/mod.rs new file mode 100644 index 0000000..23d7779 --- /dev/null +++ b/src/vk_layer/mod.rs @@ -0,0 +1,472 @@ +mod enums; +mod structs; +mod vk_handles; + +use enums::*; +use structs::*; +use vk_handles::*; +use vulkan_rs::prelude::*; + +use std::{ffi::c_void, fs::File, 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, LOG_ENABLED, LOG_FILE, OVERLAY}; + +#[no_mangle] +#[allow(non_snake_case)] +pub(crate) extern "C" fn vkNegotiateLoaderLayerInterfaceVersion( + pVersionStruct: *mut VkNegotiateLayerInterface, +) -> VkResult { + let log_enabled = match std::env::var("RFACTOR_HUD_LOG") { + Ok(var) => { + let i: u32 = var.parse().unwrap_or(0); + + i == 1 + } + Err(_) => false, + }; + + unsafe { LOG_ENABLED = log_enabled }; + + let home = std::env::var("HOME").unwrap(); + + 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!(" =================================================================="); + } + + unsafe { + OVERLAY.set_config(get_config(&home)); + } + + 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, + } + }; + + set_vk_handles(match VkTypedefHandles::new() { + Ok(handles) => handles, + Err(err) => { + write_log!(format!("failed to load typedef handles {:?}", err)); + return VK_ERROR_INITIALIZATION_FAILED; + } + }); + + VK_SUCCESS +} + +#[no_mangle] +extern "system" fn get_device_proc_addr( + _device: VkDevice, + 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(); + + if let Some(func) = Functions::get_vk_func(s) { + return func.convert(); + } + + if let Some(func) = vk_handles().handle(s) { + return func; + } + + Functions::Null.convert() +} + +#[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(); + } + }; + + let s = func_string.as_str(); + + if let Some(func) = Functions::get_vk_func(s) { + return func.convert(); + } + + if let Some(func) = vk_handles().handle(s) { + return func; + } + + Functions::Null.convert() +} + +pub(crate) 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!("instance chain info not found."); + return VK_ERROR_LAYER_NOT_PRESENT; + } + }; + + let proc_addr = chain_info.layer_info().next_instance_proc_addr; + let create_instance: PFN_vkCreateInstance = unsafe { + mem::transmute(proc_addr( + VkInstance::NULL_HANDLE, + VkString::new("vkCreateInstance").as_ptr(), + )) + }; + + chain_info.advance_layer_info(); + let result = create_instance(create_info, allocator, instance); + if result != VK_SUCCESS { + return result; + }; + + vk_handles_mut().load_instance_functions(unsafe { *instance }, proc_addr); + + 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; + } + }; + + OVERLAY.set_instance(ins); + } + + write_log!("-> created local instance handle"); + } + + VK_SUCCESS +} + +pub(crate) extern "system" fn destroy_instance( + instance: VkInstance, + allocator: *const VkAllocationCallbacks, +) { + write_log!(" ================== vulkan layer destroy instance =================="); + + unsafe { + if let Some(vk_fn) = vk_handles().handle("vkDestroyInstance") { + let destroy_instance: PFN_vkDestroyInstance = mem::transmute(vk_fn); + + destroy_instance(instance, allocator); + } + } +} + +pub(crate) 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 =================="); + + 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; + } + }; + + let proc_addr = chain_info.layer_info().next_device_proc_addr; + + chain_info.advance_layer_info(); + + let result = unsafe { + 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 => { + write_log!("failed creating device"); + return VK_ERROR_INITIALIZATION_FAILED; + } + } + }; + + if result != VK_SUCCESS { + return result; + } + + vk_handles_mut().load_device_functions(unsafe { *device }, proc_addr); + unsafe { + ACQUIRE_NEXT_IMAGE = match vk_handles().handle("vkAcquireNextImageKHR") { + Some(acquire_next_image) => mem::transmute(acquire_next_image), + None => { + write_log!("failed querying vkAcquireNextImageKHR"); + return VK_ERROR_INITIALIZATION_FAILED; + } + }; + }; + + let pdev = match PhysicalDevice::from_raw(unsafe { OVERLAY.instance() }, physical_device) { + Ok(pdev) => pdev, + Err(err) => { + write_log!(format!("failed creating physical device: {:?}", err)); + return VK_ERROR_INITIALIZATION_FAILED; + } + }; + + let queue_info = match Queue::create_non_presentable_request_info(&pdev, VK_QUEUE_GRAPHICS_BIT) + { + Ok(qi) => qi, + Err(err) => { + write_log!(format!("failed getting queue info: {:?}", err)); + 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 { + write_log!(format!( + "pCreateDeviceInfo; queue fam: {}, queue count: {}", + info.queueFamilyIndex, info.queueCount + )); + } + + write_log!(format!( + "Queue: queue fam: {}, queue count: {}", + queue_info.queue_create_info.queueFamilyIndex, queue_info.queue_create_info.queueCount + )); + } + + let ext_names = unsafe { (*create_info).extension_names() }; + + write_log!(format!("{:?}", ext_names)); + + let device = match Device::preinitialized(unsafe { *device }, proc_addr, pdev, &ext_names) { + Ok(dev) => dev, + Err(err) => { + write_log!(format!("-> local device creation failed: {:?}", err)); + return VK_ERROR_INITIALIZATION_FAILED; + } + }; + + write_log!("created device"); + + let queue = device.get_queue(queue_info.queue_family_index, queue_info.queue_index); + + write_log!("got queue from device"); + + unsafe { + OVERLAY.set_device(device); + OVERLAY.set_queue(queue); + } + + VK_SUCCESS +} + +pub(crate) extern "system" fn destroy_device( + device: VkDevice, + allocator: *const VkAllocationCallbacks, +) { + write_log!(" ================== vulkan layer destroy device =================="); + + unsafe { + if let Some(vk_fn) = vk_handles().handle("vkDestroyDevice") { + let destroy_device: PFN_vkDestroyDevice = mem::transmute(vk_fn); + + destroy_device(device, allocator); + } + } +} + +pub(crate) 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 create_swapchain: PFN_vkCreateSwapchainKHR = + match vk_handles().handle("vkCreateSwapchainKHR") { + Some(create_swapchain) => unsafe { mem::transmute(create_swapchain) }, + None => { + write_log!("failed querying vkCreateSwapchainKHR"); + return VK_ERROR_INITIALIZATION_FAILED; + } + }; + + create_swapchain(_device, create_info, _allocator, p_swapchain); + + write_log!(format!("-> created swapchain vk handle {:?}", unsafe { + *p_swapchain + })); + + let swapchain = + match unsafe { Swapchain::from_raw(OVERLAY.device(), &*create_info, *p_swapchain) } { + Ok(swapchain) => swapchain, + Err(err) => { + write_log!(format!("create swapchain failed: {:?}", err)); + return VK_ERROR_INITIALIZATION_FAILED; + } + }; + + write_log!("-> created Arc"); + + if let Err(err) = unsafe { OVERLAY.create_rendering(swapchain) } { + write_log!(format!("create overlay rendering struct failed: {:?}", err)); + return VK_ERROR_INITIALIZATION_FAILED; + } + + write_log!("-> created renderer"); + + VK_SUCCESS +} + +pub(crate) extern "system" fn acquire_next_image( + device: VkDevice, + swapchain: VkSwapchainKHR, + timeout: u64, + semaphore: VkSemaphore, + fence: VkFence, + image_index: *mut u32, +) -> VkResult { + 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), + ); + + 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) + } + } + } +} + +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, + ); + + write_log!(format!("present {} swapchain(s)", swapchains.len())); + + 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() + )); + } + } + } + } + + 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) }, + None => { + write_log!("failed querying vkQueuePresentKHR"); + return VK_ERROR_DEVICE_LOST; + } + }; + + pfn(queue, present_info) +} diff --git a/src/structs.rs b/src/vk_layer/structs.rs similarity index 99% rename from src/structs.rs rename to src/vk_layer/structs.rs index f31a301..f3870ee 100644 --- a/src/structs.rs +++ b/src/vk_layer/structs.rs @@ -1,6 +1,6 @@ #![allow(non_snake_case)] -use crate::enums::*; +use super::enums::*; use vulkan_rs::prelude::*; diff --git a/src/vk_handles.rs b/src/vk_layer/vk_handles.rs similarity index 97% rename from src/vk_handles.rs rename to src/vk_layer/vk_handles.rs index 0f171be..b157f3b 100644 --- a/src/vk_handles.rs +++ b/src/vk_layer/vk_handles.rs @@ -24,7 +24,7 @@ pub struct VkTypedefHandles { impl VkTypedefHandles { pub fn new() -> Result { Ok(Self { - typedefs: include_str!("../vk_functions") + typedefs: include_str!("../../vk_functions") .lines() .map(|s| s.to_string()) .collect(), -- 2.45.2 From 5d7e771ba1e70fa2e7c7add02c01ac022845dacc Mon Sep 17 00:00:00 2001 From: hodasemi Date: Fri, 20 Jan 2023 06:56:26 +0100 Subject: [PATCH 03/12] Fix empty entries when reconnecting to server --- .../elements/leaderboard/leaderboard_entry.rs | 101 +++++++++++------- src/overlay/elements/leaderboard/mod.rs | 38 ++++--- 2 files changed, 86 insertions(+), 53 deletions(-) diff --git a/src/overlay/elements/leaderboard/leaderboard_entry.rs b/src/overlay/elements/leaderboard/leaderboard_entry.rs index 01bdf30..7ce89dc 100644 --- a/src/overlay/elements/leaderboard/leaderboard_entry.rs +++ b/src/overlay/elements/leaderboard/leaderboard_entry.rs @@ -119,11 +119,12 @@ impl LeaderBoardEntry { pub fn update_place(&mut self, place: u8) -> Result<()> { if self.place != place { self.place_updated = true; + + self.place = place; + self.place_label.set_text(self.place)?; } - self.place = place; - - self.place_label.set_text(self.place) + Ok(()) } pub fn reset_time(&mut self) -> Result<()> { @@ -134,32 +135,57 @@ impl LeaderBoardEntry { self.time_label.set_text("---") } + pub fn force_display_behind_leader(&mut self) -> Result<()> { + match self.behind { + BehindLeader::Time(time_behind) => { + // check if we are leader + if time_behind == 0.0 { + self.time_label.set_text("---")?; + } else { + let text = if time_behind > 60.0 { + let full_minutes = (self.best_lap / 60.0).floor(); + let remainder = self.best_lap - (full_minutes * 60.0); + + format!("+{:.0}:{:.0}", full_minutes, remainder) + } else { + format!("+{:.3}", time_behind) + }; + + self.time_label.set_text(text)?; + } + } + BehindLeader::Laps(laps_behind) => { + self.time_label.set_text(format!("+{}", laps_behind))?; + } + } + + Ok(()) + } + pub fn update_time_behind_leader(&mut self, behind: BehindLeader) -> Result<()> { if self.behind != behind { self.behind = behind; - match self.behind { - BehindLeader::Time(time_behind) => { - // check if we are leader - if time_behind == 0.0 { - self.time_label.set_text("---")?; - } else { - let text = if time_behind > 60.0 { - let full_minutes = (self.best_lap / 60.0).floor(); - let remainder = self.best_lap - (full_minutes * 60.0); + self.force_display_behind_leader()?; + } - format!("+{:.0}:{:.0}", full_minutes, remainder) - } else { - format!("+{:.3}", time_behind) - }; + Ok(()) + } - self.time_label.set_text(text)?; - } - } - BehindLeader::Laps(laps_behind) => { - self.time_label.set_text(format!("+{}", laps_behind))?; - } - } + pub fn force_display_best_lap(&mut self) -> Result<()> { + if self.best_lap <= 0.0 { + self.time_label.set_text("---")?; + } else { + let text = if self.best_lap > 60.0 { + let full_minutes = (self.best_lap / 60.0).floor(); + let remainder = self.best_lap - (full_minutes * 60.0); + + format!("{:.0}:{:.3}", full_minutes, remainder) + } else { + format!("{:.3}", self.best_lap) + }; + + self.time_label.set_text(text)?; } Ok(()) @@ -169,28 +195,13 @@ impl LeaderBoardEntry { if self.best_lap != time { self.best_lap = time; - if self.best_lap <= 0.0 { - self.time_label.set_text("---")?; - } else { - let text = if self.best_lap > 60.0 { - let full_minutes = (self.best_lap / 60.0).floor(); - let remainder = self.best_lap - (full_minutes * 60.0); - - format!("{:.0}:{:.3}", full_minutes, remainder) - } else { - format!("{:.3}", self.best_lap) - }; - - self.time_label.set_text(text)?; - } + self.force_display_best_lap()?; } Ok(()) } - pub fn update_time_behind_next(&mut self, time: f64) -> Result<()> { - self.time_behind_next = time; - + pub fn force_display_behind_next(&mut self) -> Result<()> { let text = if self.time_behind_next > 60.0 { let full_minutes = (self.time_behind_next / 60.0).floor(); let remainder = self.time_behind_next - (full_minutes * 60.0); @@ -203,6 +214,16 @@ impl LeaderBoardEntry { self.time_label.set_text(text) } + pub fn update_time_behind_next(&mut self, time: f64) -> Result<()> { + if self.time_behind_next != time { + self.time_behind_next = time; + + self.force_display_behind_next()?; + } + + Ok(()) + } + pub fn needs_resorting(&self) -> bool { self.place_updated } diff --git a/src/overlay/elements/leaderboard/mod.rs b/src/overlay/elements/leaderboard/mod.rs index 141e3a6..3b27fc9 100644 --- a/src/overlay/elements/leaderboard/mod.rs +++ b/src/overlay/elements/leaderboard/mod.rs @@ -78,13 +78,15 @@ impl LeaderBoard { .to_string() } - fn update_leaderboard( + fn update_leaderboard( &mut self, vehicle_scorings: &[VehicleScoringInfoV01], f: F, + d: D, ) -> Result<()> where F: Fn(&mut LeaderBoardEntry, &VehicleScoringInfoV01) -> Result<()>, + D: Fn(&mut LeaderBoardEntry) -> Result<()>, { for vehicle_scoring in vehicle_scorings { let driver_name = Self::c_char_to_string(vehicle_scoring.mDriverName); @@ -95,6 +97,7 @@ impl LeaderBoard { .iter_mut() .find(|entry| vehicle_scoring.mID == entry.id()) { + // update existing entry Some(entry) => { if entry.name() != driver_name { entry.change_name(driver_name)?; @@ -104,8 +107,9 @@ impl LeaderBoard { f(entry, vehicle_scoring)?; } + // add new entry if not found None => { - let entry = LeaderBoardEntry::new( + let mut entry = LeaderBoardEntry::new( &self.gui_handler, vehicle_scoring.mID, driver_name, @@ -123,6 +127,8 @@ impl LeaderBoard { vehicle_scoring.mBestLapTime, )?; + d(&mut entry)?; + self.leaderboard_entries.push(entry); } } @@ -251,21 +257,27 @@ impl LeaderBoard { } fn race_leaderboard(&mut self, vehicle_scorings: &[VehicleScoringInfoV01]) -> Result<()> { - self.update_leaderboard(vehicle_scorings, |entry, scoring| { - let laps_behind = scoring.mLapsBehindLeader; + self.update_leaderboard( + vehicle_scorings, + |entry, scoring| { + let laps_behind = scoring.mLapsBehindLeader; - if laps_behind != 0 { - entry.update_time_behind_leader(BehindLeader::Laps(laps_behind)) - } else { - entry.update_time_behind_leader(BehindLeader::Time(scoring.mTimeBehindLeader)) - } - }) + if laps_behind != 0 { + entry.update_time_behind_leader(BehindLeader::Laps(laps_behind)) + } else { + entry.update_time_behind_leader(BehindLeader::Time(scoring.mTimeBehindLeader)) + } + }, + |entry| entry.force_display_behind_leader(), + ) } fn quali_leaderboard(&mut self, vehicle_scorings: &[VehicleScoringInfoV01]) -> Result<()> { - self.update_leaderboard(vehicle_scorings, |entry, scoring| { - entry.update_best_lap(scoring.mBestLapTime) - }) + self.update_leaderboard( + vehicle_scorings, + |entry, scoring| entry.update_best_lap(scoring.mBestLapTime), + |entry| entry.force_display_best_lap(), + ) } } -- 2.45.2 From 07dcbf16ff3b2992aa6047b375498b1ba5e87d62 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Fri, 20 Jan 2023 08:14:51 +0100 Subject: [PATCH 04/12] Improve delta board --- src/overlay/elements/leaderboard/mod.rs | 22 +++++++++++++++++++++- src/overlay/rendering.rs | 6 ++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/overlay/elements/leaderboard/mod.rs b/src/overlay/elements/leaderboard/mod.rs index 3b27fc9..08ac766 100644 --- a/src/overlay/elements/leaderboard/mod.rs +++ b/src/overlay/elements/leaderboard/mod.rs @@ -202,7 +202,27 @@ impl LeaderBoard { .enumerate() .find(|(_index, entry)| entry.id() == self.last_player_id) { - let mut start_index = if index >= 2 { index - 2 } else { 0 }; + let mut start_index = if index >= 2 { + if index == self.leaderboard_entries.len() - 2 { + if index >= 3 { + index - 3 + } else { + index - 2 + } + } else if index == self.leaderboard_entries.len() - 1 { + if index >= 4 { + index - 4 + } else if index >= 3 { + index - 3 + } else { + index - 2 + } + } else { + index - 2 + } + } else { + 0 + }; let max = self.leaderboard_entries.len().min(5); diff --git a/src/overlay/rendering.rs b/src/overlay/rendering.rs index 4e5f2c0..5f5c33c 100644 --- a/src/overlay/rendering.rs +++ b/src/overlay/rendering.rs @@ -20,11 +20,14 @@ pub struct Rendering { impl Rendering { pub fn new(queue: Arc>, swapchain: Arc) -> Result { crate::write_log!("-> Rendering ctor: begin"); + let vk_images = swapchain.vk_images()?; + write_log!(format!( "-> Rendering ctor: vk images ({})", vk_images.len() )); + let images = match swapchain.wrap_images(&vk_images, &queue, true) { Ok(images) => images, Err(err) => { @@ -32,9 +35,8 @@ impl Rendering { return Err(err); } }; - write_log!("-> Rendering ctor: wrapped images"); - write_log!("-> Rendering ctor: created render_target"); + write_log!("-> Rendering ctor: wrapped images"); write_log!(format!( "-> Rendering swapchain extents ({}, {})", -- 2.45.2 From bafb7cdc1c2174c78a3072ba1641e85d4d0419f7 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Fri, 20 Jan 2023 16:08:14 +0100 Subject: [PATCH 05/12] Add texture generator --- .gitignore | 1 + build.rs | 2 + .../elements/leaderboard/bg_generator.rs | 229 ++++++++++++++++++ .../elements/leaderboard/generator.frag | 8 + .../elements/leaderboard/generator.vert | 8 + src/overlay/elements/leaderboard/mod.rs | 1 + src/overlay/elements/pedals/mod.rs | 2 +- src/overlay/elements/radar/mod.rs | 2 +- 8 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 src/overlay/elements/leaderboard/bg_generator.rs create mode 100644 src/overlay/elements/leaderboard/generator.frag create mode 100644 src/overlay/elements/leaderboard/generator.vert diff --git a/.gitignore b/.gitignore index cb54759..64cf459 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ /Cargo.lock *.spv +image_to_file_*.png vk_functions \ No newline at end of file diff --git a/build.rs b/build.rs index 5586f94..dbbfd6d 100644 --- a/build.rs +++ b/build.rs @@ -14,6 +14,8 @@ const SHADER: &[&str] = &[ "src/overlay/elements/radar/single_color.frag", "src/overlay/elements/pedals/history.vert", "src/overlay/elements/pedals/history.frag", + "src/overlay/elements/leaderboard/generator.frag", + "src/overlay/elements/leaderboard/generator.vert", ]; fn query_vulkan_function_typedefs() { diff --git a/src/overlay/elements/leaderboard/bg_generator.rs b/src/overlay/elements/leaderboard/bg_generator.rs new file mode 100644 index 0000000..f0cc220 --- /dev/null +++ b/src/overlay/elements/leaderboard/bg_generator.rs @@ -0,0 +1,229 @@ +use anyhow::Result; +use cgmath::{ortho, vec2, Deg}; +use vulkan_rs::prelude::*; + +use std::{ + mem, + sync::{Arc, Mutex}, + time::Duration, +}; + +use crate::overlay::elements::PositionOnlyVertex; + +pub struct BackgroundGenerator; + +impl BackgroundGenerator { + pub fn generate( + device: &Arc, + queue: &Arc>, + image_infos: [(u32, u32); N], + ) -> Result<[Arc; N]> { + Ok(image_infos + .iter() + .map(|(width, height)| { + let image = Image::empty( + *width as u32, + *height as u32, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + VK_SAMPLE_COUNT_1_BIT, + ) + .format(VK_FORMAT_R8G8B8A8_UNORM) + .attach_sampler(Sampler::nearest_sampler().build(&device)?) + .build(&device, &queue)?; + + image.convert_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)?; + + let render_target = RenderTarget::builder() + .add_sub_pass( + SubPass::builder(image.width(), image.height()) + .set_prepared_targets(&[image.clone()], 0, [0.0, 0.0, 0.0, 1.0], true) + .build(&device, &queue)?, + ) + .build(&device)?; + + let vertex_shader = ShaderModule::from_slice( + device.clone(), + include_bytes!("generator.vert.spv"), + ShaderType::Vertex, + )?; + let fragment_shader = ShaderModule::from_slice( + device.clone(), + include_bytes!("generator.frag.spv"), + ShaderType::Fragment, + )?; + + let viewport = VkViewport { + x: 0.0, + y: 0.0, + width: image.width() as f32, + height: image.height() as f32, + minDepth: 0.0, + maxDepth: 1.0, + }; + + let scissor = VkRect2D { + offset: VkOffset2D { x: 0, y: 0 }, + extent: VkExtent2D { + width: image.width(), + height: image.height(), + }, + }; + + let pipeline = Pipeline::new_graphics() + .set_vertex_shader( + vertex_shader.clone(), + vec![VkVertexInputBindingDescription { + binding: 0, + stride: mem::size_of::() as u32, + inputRate: VK_VERTEX_INPUT_RATE_VERTEX, + }], + vec![ + // position + VkVertexInputAttributeDescription { + location: 0, + binding: 0, + format: VK_FORMAT_R32G32B32A32_SFLOAT, + offset: 0, + }, + ], + ) + .set_fragment_shader(fragment_shader.clone()) + .input_assembly(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false) + .default_depth_stencil(false, false) + .default_color_blend(vec![VkPipelineColorBlendAttachmentState::default()]) + .default_rasterization(VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE) + .default_multisample(VK_SAMPLE_COUNT_1_BIT) + .add_viewport(viewport) + .add_scissor(scissor) + .build( + device.clone(), + &PipelineLayout::builder().build(device.clone())?, + render_target.render_pass(), + 0, + )?; + + let ortho = ortho( + 0.0, + image.width() as f32, + 0.00, + image.height() as f32, + 0.0, + 1.0, + ); + + let command_buffer = + CommandBuffer::new_primary().build(device.clone(), queue.clone())?; + + // let corners = [ + // vec2(0.0, 0.0), + // vec2(0.0, image.height() as f32), + // vec2(image.width() as f32, image.height() as f32), + // vec2(image.width() as f32, 0.0), + // ]; + + // angle 70° + let angle: Deg = Deg(70.0); + let tan = angle.0.atan(); + + let corners = [ + vec2(0.0, 0.0), + vec2((image.height() as f32) / tan, image.height() as f32), + vec2(image.width() as f32, image.height() as f32), + vec2(image.width() as f32 - (image.height() as f32) / tan, 0.0), + ]; + + println!("width: {} height: {}", image.width(), image.height()); + + for corner in corners.iter() { + println!("corner: {:?}", corner); + } + + let vertices = PositionOnlyVertex::from_2d_corners(ortho, corners); + + let vertex_buffer = Buffer::builder() + .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + .set_memory_usage(MemoryUsage::CpuOnly) + .set_data(&vertices) + .build(device.clone())?; + + SingleSubmit::builder(&command_buffer, queue, |recorder| { + render_target.begin(recorder, VK_SUBPASS_CONTENTS_INLINE, 0); + + recorder.bind_pipeline(&pipeline)?; + + recorder.bind_vertex_buffer(&vertex_buffer); + recorder.draw_complete_single_instance(vertex_buffer.size() as u32); + + render_target.end(recorder); + + Ok(()) + }) + .wait_for_timeout(Duration::from_secs(1)) + .submit()?; + + Ok(image) + }) + .collect::>>>()? + .try_into() + .unwrap_or_else(|_: Vec>| { + unreachable!("create array from vec from an array") + })) + } +} + +#[cfg(test)] +mod test { + use anyhow::Result; + use vulkan_rs::prelude::*; + + use std::sync::{Arc, Mutex}; + + use super::BackgroundGenerator; + + fn create_vk_handles() -> Result<(Arc, Arc>)> { + let instance = Instance::new( + VkApplicationInfo::new( + &VkString::new("Test: image::to_file"), + 1, + &VkString::new("no name"), + 1, + VK_MAKE_VERSION(1, 3, 0), + ), + VulkanDebugInfo::default(), + InstanceExtensions::default(), + )?; + + let physical_device = PhysicalDevice::new(instance)?; + + let queue_info = Queue::create_non_presentable_request_info( + &physical_device, + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT, + )?; + + let device = Device::new( + physical_device, + DeviceExtensions::default(), + &[queue_info.queue_create_info], + DeviceFeatures::default(), + )?; + + let queue = device.get_queue(queue_info.queue_family_index, queue_info.queue_index); + + Ok((device, queue)) + } + + #[test] + fn generate_image_test() { + let (device, queue) = create_vk_handles().unwrap(); + + let images = BackgroundGenerator::generate(&device, &queue, [(120, 40)]).unwrap(); + + for (index, image) in images.iter().enumerate() { + image + .to_file(&format!("image_to_file_{}.png", index)) + .unwrap() + } + } +} diff --git a/src/overlay/elements/leaderboard/generator.frag b/src/overlay/elements/leaderboard/generator.frag new file mode 100644 index 0000000..72ade95 --- /dev/null +++ b/src/overlay/elements/leaderboard/generator.frag @@ -0,0 +1,8 @@ +#version 450 + +layout (location = 0) out vec4 out_color; + +void main() +{ + out_color = vec4(1.0, 1.0, 1.0, 1.0); +} diff --git a/src/overlay/elements/leaderboard/generator.vert b/src/overlay/elements/leaderboard/generator.vert new file mode 100644 index 0000000..126ef86 --- /dev/null +++ b/src/overlay/elements/leaderboard/generator.vert @@ -0,0 +1,8 @@ +#version 450 + +layout (location = 0) in vec4 position; + +void main() +{ + gl_Position = position; +} \ No newline at end of file diff --git a/src/overlay/elements/leaderboard/mod.rs b/src/overlay/elements/leaderboard/mod.rs index 08ac766..8b79120 100644 --- a/src/overlay/elements/leaderboard/mod.rs +++ b/src/overlay/elements/leaderboard/mod.rs @@ -1,3 +1,4 @@ +mod bg_generator; mod leaderboard_entry; use leaderboard_entry::*; diff --git a/src/overlay/elements/pedals/mod.rs b/src/overlay/elements/pedals/mod.rs index c4e057d..37134f9 100644 --- a/src/overlay/elements/pedals/mod.rs +++ b/src/overlay/elements/pedals/mod.rs @@ -89,7 +89,7 @@ impl Pedals { history_image.height(), )?; - let ortho = ortho(0.0, history_image.width() as f32, -0.01, 1.01, -1.0, 1.0); + let ortho = ortho(0.0, history_image.width() as f32, -0.01, 1.01, 0.0, 1.0); let descriptor_pool = DescriptorPool::builder() .set_layout(pipeline.descriptor_layout().clone()) diff --git a/src/overlay/elements/radar/mod.rs b/src/overlay/elements/radar/mod.rs index f0bc4bb..e4e0fd2 100644 --- a/src/overlay/elements/radar/mod.rs +++ b/src/overlay/elements/radar/mod.rs @@ -105,7 +105,7 @@ impl Radar { rendering.swapchain().width() as f32, 0.0, rendering.swapchain().height() as f32, - -1.0, + 0.0, 1.0, ); -- 2.45.2 From 09795e1cf7d3c952f437204887b935dcf8643c6c Mon Sep 17 00:00:00 2001 From: hodasemi Date: Fri, 20 Jan 2023 16:15:19 +0100 Subject: [PATCH 06/12] Fix image generation --- .../elements/leaderboard/bg_generator.rs | 41 +++++++------------ src/overlay/elements/pedals/mod.rs | 2 +- src/overlay/elements/radar/mod.rs | 2 +- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/overlay/elements/leaderboard/bg_generator.rs b/src/overlay/elements/leaderboard/bg_generator.rs index f0cc220..9cb8193 100644 --- a/src/overlay/elements/leaderboard/bg_generator.rs +++ b/src/overlay/elements/leaderboard/bg_generator.rs @@ -24,9 +24,7 @@ impl BackgroundGenerator { let image = Image::empty( *width as u32, *height as u32, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT - | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_SAMPLE_COUNT_1_BIT, ) .format(VK_FORMAT_R8G8B8A8_UNORM) @@ -109,38 +107,29 @@ impl BackgroundGenerator { image.width() as f32, 0.00, image.height() as f32, - 0.0, + -1.0, 1.0, ); let command_buffer = CommandBuffer::new_primary().build(device.clone(), queue.clone())?; - // let corners = [ - // vec2(0.0, 0.0), - // vec2(0.0, image.height() as f32), - // vec2(image.width() as f32, image.height() as f32), - // vec2(image.width() as f32, 0.0), - // ]; - // angle 70° let angle: Deg = Deg(70.0); let tan = angle.0.atan(); - let corners = [ - vec2(0.0, 0.0), - vec2((image.height() as f32) / tan, image.height() as f32), - vec2(image.width() as f32, image.height() as f32), - vec2(image.width() as f32 - (image.height() as f32) / tan, 0.0), - ]; - - println!("width: {} height: {}", image.width(), image.height()); - - for corner in corners.iter() { - println!("corner: {:?}", corner); - } - - let vertices = PositionOnlyVertex::from_2d_corners(ortho, corners); + let vertices = PositionOnlyVertex::from_2d_corners( + ortho, + [ + vec2(0.0, image.height() as f32), + vec2((image.height() as f32) / tan, 0.0), + vec2(image.width() as f32, 0.0), + vec2( + image.width() as f32 - (image.height() as f32) / tan, + image.height() as f32, + ), + ], + ); let vertex_buffer = Buffer::builder() .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) @@ -199,7 +188,7 @@ mod test { let queue_info = Queue::create_non_presentable_request_info( &physical_device, - VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT, + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT, )?; let device = Device::new( diff --git a/src/overlay/elements/pedals/mod.rs b/src/overlay/elements/pedals/mod.rs index 37134f9..c4e057d 100644 --- a/src/overlay/elements/pedals/mod.rs +++ b/src/overlay/elements/pedals/mod.rs @@ -89,7 +89,7 @@ impl Pedals { history_image.height(), )?; - let ortho = ortho(0.0, history_image.width() as f32, -0.01, 1.01, 0.0, 1.0); + let ortho = ortho(0.0, history_image.width() as f32, -0.01, 1.01, -1.0, 1.0); let descriptor_pool = DescriptorPool::builder() .set_layout(pipeline.descriptor_layout().clone()) diff --git a/src/overlay/elements/radar/mod.rs b/src/overlay/elements/radar/mod.rs index e4e0fd2..f0bc4bb 100644 --- a/src/overlay/elements/radar/mod.rs +++ b/src/overlay/elements/radar/mod.rs @@ -105,7 +105,7 @@ impl Radar { rendering.swapchain().width() as f32, 0.0, rendering.swapchain().height() as f32, - 0.0, + -1.0, 1.0, ); -- 2.45.2 From 7feb7a61ba815982f0b2f1f9f0aae18493130341 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Fri, 20 Jan 2023 17:01:21 +0100 Subject: [PATCH 07/12] Add support to create colored images --- .../elements/leaderboard/bg_generator.rs | 38 ++++++++-- .../elements/leaderboard/generator.frag | 6 +- .../elements/leaderboard/leaderboard_entry.rs | 31 +++++--- .../leaderboard/leaderboard_entry.xml | 12 ++- src/overlay/elements/leaderboard/mod.rs | 75 ++++++++++++++++--- 5 files changed, 128 insertions(+), 34 deletions(-) diff --git a/src/overlay/elements/leaderboard/bg_generator.rs b/src/overlay/elements/leaderboard/bg_generator.rs index 9cb8193..d30462a 100644 --- a/src/overlay/elements/leaderboard/bg_generator.rs +++ b/src/overlay/elements/leaderboard/bg_generator.rs @@ -16,14 +16,15 @@ impl BackgroundGenerator { pub fn generate( device: &Arc, queue: &Arc>, + color: [f32; 4], image_infos: [(u32, u32); N], ) -> Result<[Arc; N]> { Ok(image_infos .iter() .map(|(width, height)| { let image = Image::empty( - *width as u32, - *height as u32, + *width, + *height, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_SAMPLE_COUNT_1_BIT, ) @@ -36,7 +37,7 @@ impl BackgroundGenerator { let render_target = RenderTarget::builder() .add_sub_pass( SubPass::builder(image.width(), image.height()) - .set_prepared_targets(&[image.clone()], 0, [0.0, 0.0, 0.0, 1.0], true) + .set_prepared_targets(&[image.clone()], 0, [0.0, 0.0, 0.0, 0.0], true) .build(&device, &queue)?, ) .build(&device)?; @@ -69,6 +70,15 @@ impl BackgroundGenerator { }, }; + let descriptor_layout = DescriptorSetLayout::builder() + .add_layout_binding( + 0, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + VK_SHADER_STAGE_FRAGMENT_BIT, + 0, + ) + .build(device.clone())?; + let pipeline = Pipeline::new_graphics() .set_vertex_shader( vertex_shader.clone(), @@ -97,11 +107,26 @@ impl BackgroundGenerator { .add_scissor(scissor) .build( device.clone(), - &PipelineLayout::builder().build(device.clone())?, + &PipelineLayout::builder() + .add_descriptor_set_layout(&descriptor_layout) + .build(device.clone())?, render_target.render_pass(), 0, )?; + let color_buffer = Buffer::builder() + .set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) + .set_memory_usage(MemoryUsage::CpuOnly) + .set_data(&color) + .build(device.clone())?; + + let desc_pool = DescriptorPool::builder() + .set_layout(descriptor_layout) + .build(device.clone())?; + + let descriptor_set = desc_pool.prepare_set().allocate()?; + descriptor_set.update(&[DescriptorWrite::uniform_buffers(0, &[&color_buffer])])?; + let ortho = ortho( 0.0, image.width() as f32, @@ -142,6 +167,7 @@ impl BackgroundGenerator { recorder.bind_pipeline(&pipeline)?; + recorder.bind_descriptor_sets_minimal(&[&descriptor_set]); recorder.bind_vertex_buffer(&vertex_buffer); recorder.draw_complete_single_instance(vertex_buffer.size() as u32); @@ -207,7 +233,9 @@ mod test { fn generate_image_test() { let (device, queue) = create_vk_handles().unwrap(); - let images = BackgroundGenerator::generate(&device, &queue, [(120, 40)]).unwrap(); + let images = + BackgroundGenerator::generate(&device, &queue, [1.0, 0.0, 0.0, 1.0], [(120, 40)]) + .unwrap(); for (index, image) in images.iter().enumerate() { image diff --git a/src/overlay/elements/leaderboard/generator.frag b/src/overlay/elements/leaderboard/generator.frag index 72ade95..07bd8fa 100644 --- a/src/overlay/elements/leaderboard/generator.frag +++ b/src/overlay/elements/leaderboard/generator.frag @@ -1,8 +1,12 @@ #version 450 +layout (set = 0, binding = 0) uniform Color { + vec4 val; +} color; + layout (location = 0) out vec4 out_color; void main() { - out_color = vec4(1.0, 1.0, 1.0, 1.0); + out_color = color.val; } diff --git a/src/overlay/elements/leaderboard/leaderboard_entry.rs b/src/overlay/elements/leaderboard/leaderboard_entry.rs index 7ce89dc..60276d7 100644 --- a/src/overlay/elements/leaderboard/leaderboard_entry.rs +++ b/src/overlay/elements/leaderboard/leaderboard_entry.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use anyhow::Result; use ui::prelude::*; -use utilities::prelude::Color; +use vulkan_rs::prelude::*; #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] pub enum BehindLeader { @@ -22,9 +22,9 @@ pub struct LeaderBoardEntry { snippet: Arc, - name_label: Arc