vulkan_lib/vulkan-rs/src/instance.rs

1167 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())
};
}
}