use ash::vk; use tracing::{Level, event}; /// # Safety /// `str` must be a valid null-terminated C string or null. unsafe fn str_from_raw_parts<'a>(str: *const i8) -> std::borrow::Cow<'a, str> { use std::{borrow::Cow, ffi}; if str.is_null() { Cow::from("") } else { unsafe { ffi::CStr::from_ptr(str).to_string_lossy() } } } pub(super) unsafe extern "system" fn debug_callback( message_severity: vk::DebugUtilsMessageSeverityFlagsEXT, message_type: vk::DebugUtilsMessageTypeFlagsEXT, callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT<'_>, user_data: *mut core::ffi::c_void, ) -> vk::Bool32 { _ = user_data; // SAFETY: // - `callback_data` is a valid pointer to `DebugUtilsMessengerCallbackDataEXT`. // - `p_message_id_name` is a valid null-terminated C string or NULL. // - `p_message` is a valid null-terminated C string or NULL. let (message_id_number, message_id_name, message) = unsafe { let callback_data = &*callback_data; let message_id_number = callback_data.message_id_number; let message_id_name = str_from_raw_parts(callback_data.p_message_id_name); let message = str_from_raw_parts(callback_data.p_message); (message_id_number, message_id_name, message) }; match message_severity { vk::DebugUtilsMessageSeverityFlagsEXT::ERROR => { event!(target: "VK::DebugUtils", Level::ERROR, "{message_type:?} [{message_id_name}({message_id_number})]: {message}"); } vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE => { event!(target: "VK::DebugUtils", Level::TRACE, "{message_type:?} [{message_id_name}({message_id_number})]: {message}"); } vk::DebugUtilsMessageSeverityFlagsEXT::INFO => { event!(target: "VK::DebugUtils", Level::INFO, "{message_type:?} [{message_id_name}({message_id_number})]: {message}"); } vk::DebugUtilsMessageSeverityFlagsEXT::WARNING => { event!(target: "VK::DebugUtils", Level::WARN, "{message_type:?} [{message_id_name}({message_id_number})]: {message}"); } _ => unreachable!(), } vk::FALSE }