Move vk layer stuff into own directory
This commit is contained in:
parent
bd31f4fbb5
commit
8095d866c3
5 changed files with 477 additions and 474 deletions
472
src/lib.rs
472
src/lib.rs
|
@ -1,30 +1,17 @@
|
||||||
pub mod enums;
|
|
||||||
pub mod structs;
|
|
||||||
|
|
||||||
mod overlay;
|
mod overlay;
|
||||||
mod vk_handles;
|
mod vk_layer;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
ffi::c_void,
|
|
||||||
fs::{self, File, OpenOptions},
|
fs::{self, File, OpenOptions},
|
||||||
io::Write,
|
io::Write,
|
||||||
mem,
|
|
||||||
os::raw::c_char,
|
|
||||||
path::Path,
|
path::Path,
|
||||||
ptr,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use enums::*;
|
|
||||||
use overlay::{Overlay, OverlayConfig};
|
use overlay::{Overlay, OverlayConfig};
|
||||||
use structs::*;
|
|
||||||
use vk_handles::*;
|
|
||||||
use vulkan_rs::prelude::*;
|
|
||||||
|
|
||||||
static mut LOG_ENABLED: bool = true;
|
static mut LOG_ENABLED: bool = true;
|
||||||
static mut LOG_FILE: String = String::new();
|
static mut LOG_FILE: String = String::new();
|
||||||
static mut OVERLAY: Overlay = Overlay::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 {
|
pub(crate) fn logging() -> bool {
|
||||||
unsafe { LOG_ENABLED }
|
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<Swapchain>");
|
|
||||||
|
|
||||||
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) {
|
pub fn log(msg: impl ToString) {
|
||||||
assert!(logging());
|
assert!(logging());
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
use vulkan_rs::prelude::*;
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
use crate::*;
|
use super::*;
|
||||||
|
|
||||||
pub use VkLayerFunction::*;
|
pub use VkLayerFunction::*;
|
||||||
pub use VkNegotiateLayerStructType::*;
|
pub use VkNegotiateLayerStructType::*;
|
||||||
|
@ -13,6 +13,7 @@ pub enum VkNegotiateLayerStructType {
|
||||||
LAYER_NEGOTIATE_INTERFACE_STRUCT = 1,
|
LAYER_NEGOTIATE_INTERFACE_STRUCT = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
pub enum VkLayerFunction {
|
pub enum VkLayerFunction {
|
||||||
VK_LAYER_LINK_INFO = 0,
|
VK_LAYER_LINK_INFO = 0,
|
472
src/vk_layer/mod.rs
Normal file
472
src/vk_layer/mod.rs
Normal file
|
@ -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<Swapchain>");
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::enums::*;
|
use super::enums::*;
|
||||||
|
|
||||||
use vulkan_rs::prelude::*;
|
use vulkan_rs::prelude::*;
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub struct VkTypedefHandles {
|
||||||
impl VkTypedefHandles {
|
impl VkTypedefHandles {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
typedefs: include_str!("../vk_functions")
|
typedefs: include_str!("../../vk_functions")
|
||||||
.lines()
|
.lines()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect(),
|
.collect(),
|
Loading…
Reference in a new issue