use anyhow::Result; use std::{collections::HashMap, ffi::c_void, fs, mem, path::Path, ptr}; use vulkan_sys::prelude::*; static mut FN_HANDLES: Option = None; pub fn vk_handles() -> &'static VkTypedefHandles { unsafe { FN_HANDLES.as_ref().unwrap() } } pub fn vk_handles_mut() -> &'static mut VkTypedefHandles { unsafe { FN_HANDLES.as_mut().unwrap() } } pub fn set_vk_handles(handles: VkTypedefHandles) { unsafe { FN_HANDLES = Some(handles) }; } pub struct VkTypedefHandles { typedefs: Vec, functions: HashMap, instance: VkInstance, device: VkDevice, } impl VkTypedefHandles { pub fn new(symbol_files: &[impl AsRef]) -> Result { let mut symbols = Vec::new(); for symbol_file in symbol_files { let s = fs::read_to_string(symbol_file)?; symbols.append(&mut s.lines().map(|s| s.to_string()).collect()); } Ok(Self { typedefs: symbols, functions: HashMap::new(), instance: VkInstance::NULL_HANDLE, device: VkDevice::NULL_HANDLE, }) } pub fn load_instance_functions( &mut self, instance: VkInstance, proc_addr: PFN_vkGetInstanceProcAddr, ) { self.instance = instance; unsafe { for symbol in &self.typedefs { let name = VkString::new(symbol); let function = proc_addr(instance, name.as_ptr()); if mem::transmute::(function) != ptr::null() { self.functions.insert(symbol.clone(), function); } } } } pub fn load_device_functions(&mut self, device: VkDevice, proc_addr: PFN_vkGetDeviceProcAddr) { self.device = device; unsafe { for symbol in &self.typedefs { let name = VkString::new(symbol); let function = proc_addr(device, name.as_ptr()); if mem::transmute::(function) != ptr::null() { self.functions.insert(symbol.clone(), function); } } } } pub fn handle(&self, symbol_name: impl ToString) -> Option { self.functions.get(&symbol_name.to_string()).cloned() } pub fn instance(&self) -> VkInstance { self.instance } pub fn device(&self) -> VkDevice { self.device } }