1166 lines
35 KiB
Rust
1166 lines
35 KiB
Rust
use crate::prelude::*;
|
|
|
|
use anyhow::Result;
|
|
|
|
use std::collections::HashSet;
|
|
use std::fmt;
|
|
use std::mem::MaybeUninit;
|
|
use std::ptr;
|
|
use std::sync::Arc;
|
|
|
|
use std::os::raw::c_char;
|
|
use std::os::raw::c_void;
|
|
|
|
use std::ffi::CStr;
|
|
|
|
Extensions!(InstanceExtensions, {
|
|
(xlib_surface, "VK_KHR_xlib_surface"),
|
|
(wayland_surface, "VK_KHR_wayland_surface"),
|
|
(android_surface, "VK_KHR_android_surface"),
|
|
(macos_surface, "VK_KHR_macos_surface"),
|
|
(win32_surface, "VK_KHR_win32_surface"),
|
|
(surface, "VK_KHR_surface"),
|
|
(physical_device_properties2, "VK_KHR_get_physical_device_properties2"),
|
|
});
|
|
|
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
|
|
pub struct VulkanDebugInfo {
|
|
pub debugging: bool,
|
|
pub steam_layer: bool,
|
|
pub verbose: bool,
|
|
pub renderdoc: bool,
|
|
}
|
|
|
|
pub struct Instance {
|
|
_static_functions: StaticFunctions,
|
|
_entry_functions: Option<EntryFunctions>,
|
|
pub(crate) instance_functions: InstanceFunctions,
|
|
instance_wsi_functions: InstanceWSIFunctions,
|
|
physical_device_properties2_functions: PhysicalDeviceProperties2Functions,
|
|
|
|
debug_report_callback_functions: DebugReportCallbackFunctions,
|
|
instance: VkInstance,
|
|
|
|
instance_extensions: InstanceExtensions,
|
|
|
|
debug_report: Option<VkDebugReportCallbackEXT>,
|
|
|
|
api_version: u32,
|
|
}
|
|
|
|
struct Layer {
|
|
props: Vec<VkLayerProperties>,
|
|
}
|
|
|
|
impl Layer {
|
|
fn create(entry_functions: &EntryFunctions) -> Result<Layer> {
|
|
Ok(Layer {
|
|
props: Instance::enumerate_layer_properties(
|
|
entry_functions.vkEnumerateInstanceLayerProperties,
|
|
)?,
|
|
})
|
|
}
|
|
|
|
fn names(
|
|
&self,
|
|
debugging: bool,
|
|
steam_layer: bool,
|
|
verbose: bool,
|
|
renderdoc: bool,
|
|
) -> Result<Vec<VkString>> {
|
|
let mut names = Vec::new();
|
|
|
|
for i in 0..self.props.len() {
|
|
let name_string = self.props[i].layer_name()?;
|
|
let name = name_string.as_str();
|
|
|
|
if debugging && name == "VK_LAYER_KHRONOS_validation" {
|
|
names.push(name_string.clone());
|
|
}
|
|
|
|
if verbose && name == "VK_LAYER_LUNARG_api_dump" {
|
|
names.push(name_string.clone());
|
|
}
|
|
|
|
if renderdoc && name == "VK_LAYER_RENDERDOC_Capture" {
|
|
names.push(name_string.clone());
|
|
}
|
|
|
|
if steam_layer
|
|
&& (name == "VK_LAYER_VALVE_steam_overlay_64"
|
|
|| name == "VK_LAYER_VALVE_steam_overlay_32")
|
|
{
|
|
names.push(name_string.clone());
|
|
}
|
|
}
|
|
|
|
Ok(names)
|
|
}
|
|
}
|
|
|
|
fn log(msg: impl ToString) {
|
|
use std::io::Write;
|
|
|
|
let home = std::env::var("HOME").unwrap();
|
|
|
|
let log_file = format!("{}/rf2_vk_hud.log", home);
|
|
|
|
if let Ok(mut file) = std::fs::OpenOptions::new()
|
|
.append(true)
|
|
.create(true)
|
|
.open(&log_file)
|
|
{
|
|
if let Err(_) = file.write_all(format!("{}\n", msg.to_string()).as_bytes()) {}
|
|
}
|
|
}
|
|
|
|
impl Instance {
|
|
pub fn preinitialized(
|
|
instance: VkInstance,
|
|
proc_addr: PFN_vkGetInstanceProcAddr,
|
|
extensions: &[VkString],
|
|
api_version: Option<u32>,
|
|
) -> Result<Arc<Instance>> {
|
|
log("Instance::preinitialized: start");
|
|
|
|
let static_functions = StaticFunctions {
|
|
_lib: None,
|
|
vkGetInstanceProcAddr: proc_addr,
|
|
};
|
|
|
|
log("Instance::preinitialized: queried StaticFunctions");
|
|
|
|
let instance_functions = InstanceFunctions::new(&static_functions, instance);
|
|
|
|
log("Instance::preinitialized: queried InstanceFunctions");
|
|
|
|
let instance_wsi_functions = InstanceWSIFunctions::new(&static_functions, instance);
|
|
|
|
log("Instance::preinitialized: queried InstanceWSIFunctions");
|
|
|
|
let physical_device_properties2_functions =
|
|
PhysicalDeviceProperties2Functions::new(&static_functions, instance);
|
|
|
|
log("Instance::preinitialized: queried PhysicalDeviceProperties2Functions");
|
|
|
|
let debug_report_callback_functions =
|
|
DebugReportCallbackFunctions::new(&static_functions, instance);
|
|
|
|
log("Instance::preinitialized: queried DebugReportCallbackFunctions");
|
|
|
|
let instance_extensions = InstanceExtensions::from_list(extensions);
|
|
|
|
log("Instance::preinitialized: queried InstanceExtensions");
|
|
|
|
let instance = Arc::new(Instance {
|
|
_static_functions: static_functions,
|
|
_entry_functions: None,
|
|
instance_functions,
|
|
instance_wsi_functions,
|
|
physical_device_properties2_functions,
|
|
|
|
debug_report_callback_functions,
|
|
|
|
instance,
|
|
|
|
instance_extensions,
|
|
|
|
debug_report: None,
|
|
|
|
api_version: api_version.unwrap_or(VK_MAKE_VERSION(1, 0, 0)),
|
|
});
|
|
|
|
Ok(instance)
|
|
}
|
|
|
|
pub fn new(
|
|
app_info: VkApplicationInfo<'_>,
|
|
debug_info: VulkanDebugInfo,
|
|
mut extensions: InstanceExtensions,
|
|
) -> Result<Arc<Instance>> {
|
|
// required in physical device
|
|
extensions.physical_device_properties2 = true;
|
|
|
|
let static_functions = StaticFunctions::load()?;
|
|
let entry_functions = EntryFunctions::new(&static_functions);
|
|
|
|
let layers = if debug_info.debugging {
|
|
let layer_object = Layer::create(&entry_functions)?;
|
|
|
|
layer_object.names(
|
|
true,
|
|
debug_info.steam_layer,
|
|
debug_info.verbose,
|
|
debug_info.renderdoc,
|
|
)?
|
|
} else if debug_info.renderdoc {
|
|
let layer_object = Layer::create(&entry_functions)?;
|
|
|
|
// render doc only
|
|
layer_object.names(false, false, false, true)?
|
|
} else {
|
|
Vec::new()
|
|
};
|
|
|
|
let mut checked_extensions = Vec::new();
|
|
let mut extension_list = extensions.as_list();
|
|
|
|
if debug_info.debugging || debug_info.renderdoc {
|
|
extension_list.push(VkString::new("VK_EXT_debug_report"));
|
|
}
|
|
|
|
if !extension_list.is_empty() {
|
|
let extension_properties = Self::get_extension_properties(&entry_functions, &layers)?;
|
|
|
|
for extension in extension_list {
|
|
for ext_prop in &extension_properties {
|
|
if extension == *ext_prop {
|
|
checked_extensions.push(extension);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// instance create info
|
|
let layer_names = VkNames::new(layers.as_slice());
|
|
let extension_names = VkNames::new(checked_extensions.as_slice());
|
|
let instance_ci = VkInstanceCreateInfo::new(
|
|
VK_INSTANCE_CREATE_NULL_BIT,
|
|
&app_info,
|
|
&layer_names,
|
|
&extension_names,
|
|
);
|
|
|
|
println!("enabled layers ({}):", layer_names.len());
|
|
|
|
for layer_name in layer_names.iter() {
|
|
println!("\t- {:?}", layer_name);
|
|
}
|
|
|
|
println!("\nenabled instance extensions ({}):", extension_names.len());
|
|
|
|
for extension_name in extension_names.iter() {
|
|
println!("\t- {:?}", extension_name);
|
|
}
|
|
|
|
println!();
|
|
|
|
let enabled_extensions = InstanceExtensions::from_list(&checked_extensions);
|
|
|
|
if let Err(missing_extensions) = extensions.check_availability(&enabled_extensions) {
|
|
for m in missing_extensions {
|
|
println!("{}", m);
|
|
}
|
|
}
|
|
|
|
let instance = unsafe {
|
|
let mut instance = MaybeUninit::uninit();
|
|
let result =
|
|
entry_functions.vkCreateInstance(&instance_ci, ptr::null(), instance.as_mut_ptr());
|
|
|
|
if result == VK_SUCCESS {
|
|
instance.assume_init()
|
|
} else {
|
|
return Err(anyhow::Error::new(result));
|
|
}
|
|
};
|
|
|
|
let instance_functions = InstanceFunctions::new(&static_functions, instance);
|
|
let instance_wsi_functions = InstanceWSIFunctions::new(&static_functions, instance);
|
|
let physical_device_properties2_functions =
|
|
PhysicalDeviceProperties2Functions::new(&static_functions, instance);
|
|
let debug_report_callback_functions =
|
|
DebugReportCallbackFunctions::new(&static_functions, instance);
|
|
|
|
let mut instance = Instance {
|
|
_static_functions: static_functions,
|
|
_entry_functions: Some(entry_functions),
|
|
instance_functions,
|
|
instance_wsi_functions,
|
|
physical_device_properties2_functions,
|
|
|
|
debug_report_callback_functions,
|
|
|
|
instance,
|
|
|
|
instance_extensions: enabled_extensions,
|
|
|
|
debug_report: None,
|
|
|
|
api_version: app_info.apiVersion,
|
|
};
|
|
|
|
if !layers.is_empty() {
|
|
if let Err(msg) = instance.create_debug_report() {
|
|
println!("failed creating debug report: {}", msg);
|
|
}
|
|
}
|
|
|
|
Ok(Arc::new(instance))
|
|
}
|
|
|
|
pub(crate) fn api_version(&self) -> u32 {
|
|
self.api_version
|
|
}
|
|
|
|
pub fn enabled_extensions(&self) -> &InstanceExtensions {
|
|
&self.instance_extensions
|
|
}
|
|
}
|
|
|
|
impl_vk_handle!(Instance, VkInstance, instance);
|
|
|
|
// private
|
|
impl Instance {
|
|
fn create_debug_report(&mut self) -> Result<()> {
|
|
let debug_report_info = VkDebugReportCallbackCreateInfoEXT::new(
|
|
VK_DEBUG_REPORT_WARNING_BIT_EXT
|
|
| VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT
|
|
| VK_DEBUG_REPORT_ERROR_BIT_EXT,
|
|
Instance::debug_report_callback,
|
|
);
|
|
|
|
let debug_report = self.create_debug_report_callbacks(&debug_report_info)?;
|
|
|
|
self.debug_report = Some(debug_report);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn get_extension_properties(
|
|
entry_functions: &EntryFunctions,
|
|
layers: &[VkString],
|
|
) -> Result<Vec<VkString>> {
|
|
let mut properties = HashSet::new();
|
|
|
|
let default_properties = Self::enumerate_extension_properties(
|
|
entry_functions.vkEnumerateInstanceExtensionProperties,
|
|
None,
|
|
)?;
|
|
|
|
for property in default_properties {
|
|
let prop_string = VkString::new(&property.extension_name()?);
|
|
|
|
properties.insert(prop_string);
|
|
}
|
|
|
|
for layer in layers {
|
|
let tmp_properties = Self::enumerate_extension_properties(
|
|
entry_functions.vkEnumerateInstanceExtensionProperties,
|
|
Some(layer),
|
|
)?;
|
|
|
|
for property in tmp_properties {
|
|
let prop_string = VkString::new(&property.extension_name()?);
|
|
|
|
properties.insert(prop_string);
|
|
}
|
|
}
|
|
|
|
Ok(properties.iter().cloned().collect())
|
|
}
|
|
}
|
|
|
|
// debug
|
|
impl Instance {
|
|
extern "system" fn debug_report_callback(
|
|
flags: VkDebugReportFlagsEXT,
|
|
object_type: VkDebugReportObjectTypeEXT,
|
|
_src_object: u64,
|
|
_location: usize,
|
|
_msg_code: i32,
|
|
_layer_prefix: *const c_char,
|
|
msg: *const c_char,
|
|
_user_data: *mut c_void,
|
|
) -> VkBool32 {
|
|
let mut output: String = String::new();
|
|
|
|
output += match flags {
|
|
VK_DEBUG_REPORT_INFORMATION_BIT_EXT => "INFO",
|
|
VK_DEBUG_REPORT_WARNING_BIT_EXT => "WARNING",
|
|
VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT => "PERFORMANCE",
|
|
VK_DEBUG_REPORT_ERROR_BIT_EXT => "ERROR",
|
|
VK_DEBUG_REPORT_DEBUG_BIT_EXT => "DEBUG",
|
|
};
|
|
|
|
output += ": OBJ( ";
|
|
|
|
output += match object_type {
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT => "UNKNOWN",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT => "INSTANCE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT => "PHYSICAL DEVICE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT => "DEVICE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT => "QUEUE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT => "SEMAPHORE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT => "COMMAND BUFFER",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT => "FENCE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT => "DEVICE MEMORY",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT => "BUFFER",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT => "IMAGE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT => "EVENT",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT => "QUERY POOL",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT => "BUFFER VIEW",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT => "IMAGE VIEW",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT => "SHADER MODULE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT => "PIPELINE CACHE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT => "PIPELINE LAYOUT",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT => "RENDER PASS",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT => "PIPELINE",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT => "DESCRIPTOR SET LAYOUT",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT => "SAMPLER",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT => "DESCRIPTOR POOL",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT => "DESCRIPTOR SET",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT => "FRAME BUFFER",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT => "COMMAND POOL",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT => "SURFACE KHR",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT => "SWAPCHAIN KHR",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT => "DEBUG REPORT",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT => "DISPLAY KHR",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT => "DISPLAY MODE KHR",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT => "OBJECT TABLE NVX",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT => {
|
|
"INDIRECT COMMANDS LAYOUT NVX"
|
|
}
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT => "VALIDATION CACHE ",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT => "SAMPLER YCBCR CONVERSION ",
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT => {
|
|
"DESCRIPTOR UPDATE TEMPLATE "
|
|
}
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT => {
|
|
"ACCELERATION STRUCTURE NV"
|
|
}
|
|
};
|
|
|
|
let s = match VkString::try_from(msg) {
|
|
Ok(s) => s,
|
|
Err(err) => {
|
|
println!("{}", err);
|
|
|
|
return VK_FALSE;
|
|
}
|
|
};
|
|
|
|
output += " ):\n\t";
|
|
output += s.as_str();
|
|
|
|
println!("{}", output);
|
|
|
|
VK_TRUE
|
|
}
|
|
}
|
|
|
|
impl fmt::Debug for Instance {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "Instance (VkInstance: {:#?})", self.instance)
|
|
}
|
|
}
|
|
|
|
impl Drop for Instance {
|
|
fn drop(&mut self) {
|
|
if let Some(debug_report) = &self.debug_report {
|
|
self.destroy_debug_report_callbacks(*debug_report);
|
|
}
|
|
|
|
self.destroy_instance();
|
|
}
|
|
}
|
|
|
|
// private wrapper
|
|
impl Instance {
|
|
#[inline]
|
|
fn enumerate_layer_properties(
|
|
enumerate_instance_layer_properties: PFN_vkEnumerateInstanceLayerProperties,
|
|
) -> Result<Vec<VkLayerProperties>> {
|
|
let mut property_count: u32 = 0;
|
|
|
|
// get the amount of properties
|
|
let result = enumerate_instance_layer_properties(&mut property_count, ptr::null_mut());
|
|
|
|
if result != VK_SUCCESS {
|
|
return Err(anyhow::Error::new(result));
|
|
}
|
|
|
|
let mut properties = Vec::with_capacity(property_count as usize);
|
|
unsafe { properties.set_len(property_count as usize) };
|
|
|
|
// get the properties
|
|
let result =
|
|
enumerate_instance_layer_properties(&mut property_count, properties.as_mut_ptr());
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(properties)
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn enumerate_extension_properties(
|
|
enumerate_instance_extension_properties: PFN_vkEnumerateInstanceExtensionProperties,
|
|
layer_name: Option<&VkString>,
|
|
) -> Result<Vec<VkExtensionProperties>> {
|
|
let mut count = 0;
|
|
let name = match layer_name {
|
|
Some(name) => name.as_ptr(),
|
|
None => ptr::null(),
|
|
};
|
|
|
|
let mut result = enumerate_instance_extension_properties(name, &mut count, ptr::null_mut());
|
|
|
|
if result != VK_SUCCESS {
|
|
return Err(anyhow::Error::new(result));
|
|
}
|
|
|
|
let mut properties = Vec::with_capacity(count as usize);
|
|
unsafe { properties.set_len(count as usize) };
|
|
|
|
result = enumerate_instance_extension_properties(name, &mut count, properties.as_mut_ptr());
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(properties)
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn destroy_instance(&self) {
|
|
unsafe {
|
|
self.instance_functions
|
|
.vkDestroyInstance(self.instance, ptr::null());
|
|
}
|
|
}
|
|
}
|
|
|
|
// public, wrapped vulkan calls
|
|
impl Instance {
|
|
#[inline]
|
|
pub fn create_debug_report_callbacks(
|
|
&self,
|
|
debug_report_callback_create_info: &VkDebugReportCallbackCreateInfoEXT,
|
|
) -> Result<VkDebugReportCallbackEXT> {
|
|
unsafe {
|
|
let mut debug_report_callback = MaybeUninit::uninit();
|
|
|
|
let result = self
|
|
.debug_report_callback_functions
|
|
.vkCreateDebugReportCallbackEXT(
|
|
self.instance,
|
|
debug_report_callback_create_info,
|
|
ptr::null(),
|
|
debug_report_callback.as_mut_ptr(),
|
|
);
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(debug_report_callback.assume_init())
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn destroy_debug_report_callbacks(&self, debug_report_callback: VkDebugReportCallbackEXT) {
|
|
unsafe {
|
|
self.debug_report_callback_functions
|
|
.vkDestroyDebugReportCallbackEXT(self.instance, debug_report_callback, ptr::null())
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn get_device_proc_addr(&self, device: VkDevice, name: VkString) -> PFN_vkVoidFunction {
|
|
unsafe {
|
|
self.instance_functions
|
|
.vkGetDeviceProcAddr(device, name.as_ptr())
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn get_device_proc_addr_raw(&self, device: VkDevice, name: &CStr) -> PFN_vkVoidFunction {
|
|
unsafe {
|
|
self.instance_functions
|
|
.vkGetDeviceProcAddr(device, name.as_ptr())
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn enumerate_physical_devices(&self) -> Result<Vec<VkPhysicalDevice>> {
|
|
let mut count = 0;
|
|
|
|
let result = unsafe {
|
|
self.instance_functions.vkEnumeratePhysicalDevices(
|
|
self.instance,
|
|
&mut count,
|
|
ptr::null_mut(),
|
|
)
|
|
};
|
|
|
|
if result != VK_SUCCESS {
|
|
return Err(anyhow::Error::new(result));
|
|
}
|
|
|
|
let mut physical_devices = Vec::with_capacity(count as usize);
|
|
unsafe { physical_devices.set_len(count as usize) };
|
|
|
|
let result = unsafe {
|
|
self.instance_functions.vkEnumeratePhysicalDevices(
|
|
self.instance,
|
|
&mut count,
|
|
physical_devices.as_mut_ptr(),
|
|
)
|
|
};
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(physical_devices)
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_properties(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> VkPhysicalDeviceProperties {
|
|
unsafe {
|
|
let mut physical_device_properties = MaybeUninit::uninit();
|
|
|
|
self.instance_functions.vkGetPhysicalDeviceProperties(
|
|
physical_device,
|
|
physical_device_properties.as_mut_ptr(),
|
|
);
|
|
|
|
physical_device_properties.assume_init()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_features(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> VkPhysicalDeviceFeatures {
|
|
unsafe {
|
|
let mut physical_device_features = MaybeUninit::uninit();
|
|
|
|
self.instance_functions.vkGetPhysicalDeviceFeatures(
|
|
physical_device,
|
|
physical_device_features.as_mut_ptr(),
|
|
);
|
|
|
|
physical_device_features.assume_init()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_format_properties(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
format: VkFormat,
|
|
) -> VkFormatProperties {
|
|
unsafe {
|
|
let mut physical_device_format_properties = MaybeUninit::uninit();
|
|
|
|
self.instance_functions.vkGetPhysicalDeviceFormatProperties(
|
|
physical_device,
|
|
format,
|
|
physical_device_format_properties.as_mut_ptr(),
|
|
);
|
|
|
|
physical_device_format_properties.assume_init()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_queue_family_properties(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> Vec<VkQueueFamilyProperties> {
|
|
let mut count = 0;
|
|
|
|
unsafe {
|
|
self.instance_functions
|
|
.vkGetPhysicalDeviceQueueFamilyProperties(
|
|
physical_device,
|
|
&mut count,
|
|
ptr::null_mut(),
|
|
);
|
|
}
|
|
|
|
let mut queue_family_properties = Vec::with_capacity(count as usize);
|
|
unsafe { queue_family_properties.set_len(count as usize) };
|
|
|
|
unsafe {
|
|
self.instance_functions
|
|
.vkGetPhysicalDeviceQueueFamilyProperties(
|
|
physical_device,
|
|
&mut count,
|
|
queue_family_properties.as_mut_ptr(),
|
|
);
|
|
}
|
|
|
|
queue_family_properties
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_memory_properties(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> VkPhysicalDeviceMemoryProperties {
|
|
unsafe {
|
|
let mut physical_device_memory_properties = MaybeUninit::uninit();
|
|
|
|
self.instance_functions.vkGetPhysicalDeviceMemoryProperties(
|
|
physical_device,
|
|
physical_device_memory_properties.as_mut_ptr(),
|
|
);
|
|
|
|
physical_device_memory_properties.assume_init()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_sparse_image_format_properties<T>(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
format: VkFormat,
|
|
ty: VkImageType,
|
|
samples: VkSampleCountFlags,
|
|
usage: impl Into<VkImageUsageFlagBits>,
|
|
tiling: VkImageTiling,
|
|
) -> Vec<VkSparseImageFormatProperties> {
|
|
let mut count = 0;
|
|
let usage = usage.into();
|
|
|
|
unsafe {
|
|
self.instance_functions
|
|
.vkGetPhysicalDeviceSparseImageFormatProperties(
|
|
physical_device,
|
|
format,
|
|
ty,
|
|
samples,
|
|
usage,
|
|
tiling,
|
|
&mut count,
|
|
ptr::null_mut(),
|
|
);
|
|
}
|
|
|
|
let mut sparse_image_formats = Vec::with_capacity(count as usize);
|
|
unsafe { sparse_image_formats.set_len(count as usize) };
|
|
|
|
unsafe {
|
|
self.instance_functions
|
|
.vkGetPhysicalDeviceSparseImageFormatProperties(
|
|
physical_device,
|
|
format,
|
|
ty,
|
|
samples,
|
|
usage,
|
|
tiling,
|
|
&mut count,
|
|
sparse_image_formats.as_mut_ptr(),
|
|
);
|
|
}
|
|
|
|
sparse_image_formats
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_image_format_properties(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
format: VkFormat,
|
|
image_type: VkImageType,
|
|
tiling: VkImageTiling,
|
|
usage: impl Into<VkImageUsageFlagBits>,
|
|
flags: impl Into<VkImageCreateFlagBits>,
|
|
) -> Result<VkImageFormatProperties> {
|
|
unsafe {
|
|
let mut image_format_properties = MaybeUninit::uninit();
|
|
|
|
let result = self
|
|
.instance_functions
|
|
.vkGetPhysicalDeviceImageFormatProperties(
|
|
physical_device,
|
|
format,
|
|
image_type,
|
|
tiling,
|
|
usage.into(),
|
|
flags.into(),
|
|
image_format_properties.as_mut_ptr(),
|
|
);
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(image_format_properties.assume_init())
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn create_device<'a>(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
device_create_info: &'a VkDeviceCreateInfo<'a>,
|
|
) -> Result<VkDevice> {
|
|
unsafe {
|
|
let mut device = MaybeUninit::uninit();
|
|
|
|
let result = self.instance_functions.vkCreateDevice(
|
|
physical_device,
|
|
device_create_info,
|
|
ptr::null(),
|
|
device.as_mut_ptr(),
|
|
);
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(device.assume_init())
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_surface_support(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
queue_family_index: u32,
|
|
surface: VkSurfaceKHR,
|
|
) -> Result<bool> {
|
|
unsafe {
|
|
let mut supported = MaybeUninit::uninit();
|
|
|
|
let result = self
|
|
.instance_wsi_functions
|
|
.vkGetPhysicalDeviceSurfaceSupportKHR(
|
|
physical_device,
|
|
queue_family_index,
|
|
surface,
|
|
supported.as_mut_ptr(),
|
|
);
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(supported.assume_init() == VK_TRUE)
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_surface_capabilities(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
surface: VkSurfaceKHR,
|
|
) -> Result<VkSurfaceCapabilitiesKHR> {
|
|
unsafe {
|
|
let mut surface_capabilities = MaybeUninit::uninit();
|
|
|
|
let result = self
|
|
.instance_wsi_functions
|
|
.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
|
|
physical_device,
|
|
surface,
|
|
surface_capabilities.as_mut_ptr(),
|
|
);
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(surface_capabilities.assume_init())
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_surface_formats(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
surface: VkSurfaceKHR,
|
|
) -> Result<Vec<VkSurfaceFormatKHR>> {
|
|
let mut count = 0;
|
|
|
|
let result = unsafe {
|
|
self.instance_wsi_functions
|
|
.vkGetPhysicalDeviceSurfaceFormatsKHR(
|
|
physical_device,
|
|
surface,
|
|
&mut count,
|
|
ptr::null_mut(),
|
|
)
|
|
};
|
|
|
|
if result != VK_SUCCESS {
|
|
return Err(anyhow::Error::new(result));
|
|
}
|
|
|
|
let mut surface_formats = Vec::with_capacity(count as usize);
|
|
unsafe { surface_formats.set_len(count as usize) };
|
|
|
|
let result = unsafe {
|
|
self.instance_wsi_functions
|
|
.vkGetPhysicalDeviceSurfaceFormatsKHR(
|
|
physical_device,
|
|
surface,
|
|
&mut count,
|
|
surface_formats.as_mut_ptr(),
|
|
)
|
|
};
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(surface_formats)
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_present_modes(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
surface: VkSurfaceKHR,
|
|
) -> Result<Vec<VkPresentModeKHR>> {
|
|
let mut count = 0;
|
|
|
|
let result = unsafe {
|
|
self.instance_wsi_functions
|
|
.vkGetPhysicalDeviceSurfacePresentModesKHR(
|
|
physical_device,
|
|
surface,
|
|
&mut count,
|
|
ptr::null_mut(),
|
|
)
|
|
};
|
|
|
|
if result != VK_SUCCESS {
|
|
return Err(anyhow::Error::new(result));
|
|
}
|
|
|
|
let mut surface_present_modes = Vec::with_capacity(count as usize);
|
|
unsafe { surface_present_modes.set_len(count as usize) };
|
|
|
|
let result = unsafe {
|
|
self.instance_wsi_functions
|
|
.vkGetPhysicalDeviceSurfacePresentModesKHR(
|
|
physical_device,
|
|
surface,
|
|
&mut count,
|
|
surface_present_modes.as_mut_ptr(),
|
|
)
|
|
};
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(surface_present_modes)
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn enumerate_device_extensions(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> Result<Vec<VkExtensionProperties>> {
|
|
let mut count = 0;
|
|
|
|
let result = unsafe {
|
|
self.instance_functions
|
|
.vkEnumerateDeviceExtensionProperties(
|
|
physical_device,
|
|
ptr::null(),
|
|
&mut count,
|
|
ptr::null_mut(),
|
|
)
|
|
};
|
|
|
|
if result != VK_SUCCESS {
|
|
return Err(anyhow::Error::new(result));
|
|
}
|
|
|
|
let mut extension_properties = Vec::with_capacity(count as usize);
|
|
unsafe { extension_properties.set_len(count as usize) };
|
|
|
|
let result = unsafe {
|
|
self.instance_functions
|
|
.vkEnumerateDeviceExtensionProperties(
|
|
physical_device,
|
|
ptr::null(),
|
|
&mut count,
|
|
extension_properties.as_mut_ptr(),
|
|
)
|
|
};
|
|
|
|
if result == VK_SUCCESS {
|
|
Ok(extension_properties)
|
|
} else {
|
|
Err(anyhow::Error::new(result))
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_properties2(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
device_properties: &mut VkPhysicalDeviceProperties2KHR,
|
|
) {
|
|
unsafe {
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceProperties2KHR(physical_device, device_properties);
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_features2(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
device_features: &mut VkPhysicalDeviceFeatures2KHR,
|
|
) {
|
|
unsafe {
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceFeatures2KHR(physical_device, device_features);
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_format_properties2(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> VkFormatProperties2KHR<'_> {
|
|
unsafe {
|
|
let mut handle = MaybeUninit::uninit();
|
|
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceFormatProperties2KHR(physical_device, handle.as_mut_ptr());
|
|
|
|
handle.assume_init()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_image_format_properties2(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
image_format_info: &VkPhysicalDeviceImageFormatInfo2KHR,
|
|
) -> VkImageFormatProperties2KHR<'_> {
|
|
unsafe {
|
|
let mut handle = MaybeUninit::uninit();
|
|
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceImageFormatProperties2KHR(
|
|
physical_device,
|
|
image_format_info,
|
|
handle.as_mut_ptr(),
|
|
);
|
|
|
|
handle.assume_init()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_queue_family_properties2(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> Vec<VkQueueFamilyProperties2KHR> {
|
|
let mut count = 0;
|
|
|
|
unsafe {
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceQueueFamilyProperties2KHR(
|
|
physical_device,
|
|
&mut count,
|
|
ptr::null_mut(),
|
|
)
|
|
};
|
|
|
|
let mut family_queue_properties = Vec::with_capacity(count as usize);
|
|
unsafe { family_queue_properties.set_len(count as usize) };
|
|
|
|
unsafe {
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceQueueFamilyProperties2KHR(
|
|
physical_device,
|
|
&mut count,
|
|
family_queue_properties.as_mut_ptr(),
|
|
)
|
|
};
|
|
|
|
family_queue_properties
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_memory_properties2(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> VkPhysicalDeviceMemoryProperties2KHR {
|
|
unsafe {
|
|
let mut handle = MaybeUninit::uninit();
|
|
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceMemoryProperties2KHR(physical_device, handle.as_mut_ptr());
|
|
|
|
handle.assume_init()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_memory_budget(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
) -> (VkPhysicalDeviceMemoryBudgetPropertiesEXT, u32) {
|
|
unsafe {
|
|
let mut properties = VkPhysicalDeviceMemoryProperties2KHR::default();
|
|
let mut memory_budget = VkPhysicalDeviceMemoryBudgetPropertiesEXT::default();
|
|
properties.chain(&mut memory_budget);
|
|
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceMemoryProperties2KHR(physical_device, &mut properties);
|
|
|
|
(memory_budget, properties.memoryProperties.memoryHeapCount)
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn physical_device_sparse_image_format_properties2(
|
|
&self,
|
|
physical_device: VkPhysicalDevice,
|
|
format_info: &VkPhysicalDeviceSparseImageFormatInfo2KHR,
|
|
) -> Vec<VkSparseImageFormatProperties2KHR> {
|
|
let mut count = 0;
|
|
|
|
unsafe {
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
|
|
physical_device,
|
|
format_info,
|
|
&mut count,
|
|
ptr::null_mut(),
|
|
)
|
|
};
|
|
|
|
let mut sparse_image_formats = Vec::with_capacity(count as usize);
|
|
unsafe { sparse_image_formats.set_len(count as usize) };
|
|
|
|
unsafe {
|
|
self.physical_device_properties2_functions
|
|
.vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
|
|
physical_device,
|
|
format_info,
|
|
&mut count,
|
|
sparse_image_formats.as_mut_ptr(),
|
|
)
|
|
};
|
|
|
|
sparse_image_formats
|
|
}
|
|
|
|
#[inline]
|
|
pub fn destroy_surface(&self, surface: VkSurfaceKHR) {
|
|
unsafe {
|
|
self.instance_wsi_functions
|
|
.vkDestroySurfaceKHR(self.instance, surface, ptr::null())
|
|
};
|
|
}
|
|
}
|