#[allow(unused)]
mod native;
pub mod vk {
pub use native::VkPhysicalDeviceProperties as PhysicalDeviceProperties;
pub use native::VkQueueFamilyProperties as QueueFamilyProperties;
pub use native::VkPhysicalDeviceFeatures as PhysicalDeviceFeatures;
use crate::*;
pub struct Instance {
__instance: native::VkInstance,
__validation: native::VkDebugUtilsMessengerEXT,
}
impl Drop for Instance {
fn drop(&mut self) {
unsafe {
if cfg!(debug_assertions) {
assert!(!self.__validation.is_null());
let vk_destroy_debug_utils_messenger_ext:
unsafe extern "system" fn(
native::VkInstance,
native::VkDebugUtilsMessengerEXT,
*const ::std::ffi::c_void)
= std::mem::transmute(native::vkGetInstanceProcAddr
(self.__instance,
std::ffi::CString::new("vkDestroyDebugUtilsMessengerEXT")
.unwrap()
.to_owned()
.as_ptr()));
vk_destroy_debug_utils_messenger_ext(self.__instance, self.__validation, std::ptr::null());
}
native::vkDestroyInstance(self.__instance, std::ptr::null());
}
}
}
pub struct PhysicalDevice {
__physical_device: native::VkPhysicalDevice,
}
pub trait InstanceMethods {
fn enumerate_physical_devices(&self) -> Vec<PhysicalDevice>;
}
impl InstanceMethods for Instance {
fn enumerate_physical_devices(&self) -> Vec<PhysicalDevice> {
unsafe {
let mut num_devices: u32 = 0;
native::vkEnumeratePhysicalDevices(self.__instance, &mut num_devices, std::ptr::null_mut());
assert!(num_devices > 0);
let mut physical_devices: Vec<native::VkPhysicalDevice> = Vec::with_capacity(num_devices as usize);
native::vkEnumeratePhysicalDevices(self.__instance, &mut num_devices, physical_devices.as_mut_ptr());
physical_devices.set_len(num_devices as usize);
let mut devices: Vec<PhysicalDevice> = Vec::with_capacity(num_devices as usize);
for i in 0..num_devices {
dbg!(physical_devices[i as usize]);
let device = PhysicalDevice { __physical_device: physical_devices[i as usize] };
assert!(!device.__physical_device.is_null());
devices.push(device);
}
return devices;
}
}
}
pub trait PhysicalDeviceMethods {
fn get_properties(&self) -> native::VkPhysicalDeviceProperties;
fn get_queue_family_properties(&self) -> Vec<native::VkQueueFamilyProperties>;
fn get_features(&self) -> native::VkPhysicalDeviceFeatures;
}
impl PhysicalDeviceMethods for PhysicalDevice {
fn get_properties(&self) -> native::VkPhysicalDeviceProperties {
unsafe {
let mut properties: native::VkPhysicalDeviceProperties = std::mem::zeroed();
native::vkGetPhysicalDeviceProperties(self.__physical_device, &mut properties);
return properties;
}
}
fn get_queue_family_properties(&self) -> Vec<native::VkQueueFamilyProperties> {
unsafe {
let mut num_queue_families: u32 = 0;
native::vkGetPhysicalDeviceQueueFamilyProperties(self.__physical_device, &mut num_queue_families, std::ptr::null_mut());
assert!(num_queue_families > 0);
let mut queue_families: Vec<native::VkQueueFamilyProperties> = Vec::with_capacity(num_queue_families as usize);
native::vkGetPhysicalDeviceQueueFamilyProperties(self.__physical_device, &mut num_queue_families, queue_families.as_mut_ptr());
queue_families.set_len(num_queue_families as usize);
return queue_families;
}
}
fn get_features(&self) -> native::VkPhysicalDeviceFeatures {
unsafe {
let mut features: native::VkPhysicalDeviceFeatures = std::mem::zeroed();
native::vkGetPhysicalDeviceFeatures(self.__physical_device, &mut features);
return features;
}
}
}
pub fn make_version(major: u32, minor: u32, patch: u32) -> u32 {
return (patch<<0) | (minor<<12) | (major<<22) | (0<<29);
}
#[cfg(debug_assertions)]
extern "C" fn debug_callback(
_message_severity: native::VkDebugUtilsMessageSeverityFlagBitsEXT,
_message_types: native::VkDebugUtilsMessageTypeFlagsEXT,
_callback_data: *const native::VkDebugUtilsMessengerCallbackDataEXT,
_user_data: *mut ::std::os::raw::c_void,
) -> native::VkBool32 {
unsafe {
let message = std::ffi::CStr::from_ptr((*_callback_data).pMessage);
if (_message_severity &
(native::VkDebugUtilsMessageSeverityFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
|native::VkDebugUtilsMessageSeverityFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT))
!= 0 {
panic!("Failed validating, message from layer: {:?}", message);
}
println!("{}", format!("Validation layer debug: {}", message.to_str().unwrap()));
}
return native::VK_TRUE;
}
#[cfg(debug_assertions)]
fn setup_validation_layer(instance: native::VkInstance) -> native::VkDebugUtilsMessengerEXT {
let debug_utils_create_info = native::VkDebugUtilsMessengerCreateInfoEXT {
sType: native::VkStructureType_VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
pNext: std::ptr::null(),
flags: 0,
messageSeverity:
native::VkDebugUtilsMessageSeverityFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
native::VkDebugUtilsMessageSeverityFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
native::VkDebugUtilsMessageSeverityFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
native::VkDebugUtilsMessageSeverityFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
messageType:
native::VkDebugUtilsMessageTypeFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
native::VkDebugUtilsMessageTypeFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
native::VkDebugUtilsMessageTypeFlagBitsEXT_VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
pfnUserCallback: Some(debug_callback),
pUserData: std::ptr::null_mut(),
};
unsafe {
let vk_create_debug_utils_messenger_ext:
unsafe extern "system" fn(
native::VkInstance,
*const native::VkDebugUtilsMessengerCreateInfoEXT,
*const ::std::ffi::c_void,
*mut native::VkDebugUtilsMessengerEXT)
-> native::VkResult
= std::mem::transmute(native::vkGetInstanceProcAddr
(instance,
std::ffi::CString::new("vkCreateDebugUtilsMessengerEXT")
.unwrap()
.to_owned()
.as_ptr()));
let mut out: native::VkDebugUtilsMessengerEXT = std::mem::zeroed();
vk_create_debug_utils_messenger_ext(instance, &debug_utils_create_info, std::ptr::null(), &mut out);
return out;
}
}
pub fn create_instance() -> Instance {
let enabled_layers: Vec<&str> =
vec!["VK_LAYER_KHRONOS_validation\0"];
let layer_count = enabled_layers.len();
let enabled_layers: *const *const i8 = Box::into_raw(enabled_layers.into_boxed_slice()).cast_const() as *const *const i8;
let enabled_exts: Vec<&str> =
vec!["VK_EXT_debug_utils\0"];
let ext_count = enabled_exts.len();
let enabled_exts: *const *const i8 = Box::into_raw(enabled_exts.into_boxed_slice()).cast_const() as *const *const i8;
let application_info = native::VkApplicationInfo {
sType: native::VkStructureType_VK_STRUCTURE_TYPE_APPLICATION_INFO,
pNext: std::ptr::null(),
pApplicationName: c"vulk".as_ptr(),
applicationVersion: make_version(0, 1, 0),
pEngineName: c"vulk".as_ptr(),
engineVersion: make_version(0, 1, 0),
apiVersion: make_version(1, 3, 0),
};
let instance_info = native::VkInstanceCreateInfo {
sType: native::VkStructureType_VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
pNext: std::ptr::null(),
flags: 0,
pApplicationInfo: &application_info,
enabledLayerCount: if cfg!(debug_assertions) { layer_count as u32 } else { 0 },
ppEnabledLayerNames: if cfg!(debug_assertions) { enabled_layers } else { std::ptr::null() },
enabledExtensionCount: if cfg!(debug_assertions) { ext_count as u32 } else { 0 },
ppEnabledExtensionNames: if cfg!(debug_assertions) { enabled_exts } else { std::ptr::null() },
};
unsafe {
let mut instance: native::VkInstance = { std::mem::zeroed() };
native::vkCreateInstance(&instance_info, std::ptr::null(), &mut instance);
assert!(!instance.is_null());
#[cfg(debug_assertions)] {
let validation = setup_validation_layer(instance);
return Instance { __instance: instance, __validation: validation};
}
#[cfg(not(debug_assertions))]
{
return Instance { __instance: instance, __validation: std::ptr::null_mut()};
}
}
}
}