Skip to content

Commit

Permalink
vulkan: Log validation layer messages during instance creation/destru…
Browse files Browse the repository at this point in the history
…ction (#4586)
  • Loading branch information
exrook authored Nov 6, 2023
1 parent bc7f4be commit e7e2f2a
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 45 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ Bottom level categories:

For naga changelogs at or before v0.14.0. See [naga's changelog](naga/CHANGELOG.md).

### Changes

#### General

- Log vulkan validation layer messages during instance creation and destruction: By @exrook in [#4586](https://github.com/gfx-rs/wgpu/pull/4586)

### Bug Fixes

#### WGL
Expand Down
114 changes: 69 additions & 45 deletions wgpu-hal/src/vulkan/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,17 @@ unsafe extern "system" fn debug_utils_messenger_callback(
vk::FALSE
}

impl super::DebugUtilsCreateInfo {
fn to_vk_create_info(&self) -> vk::DebugUtilsMessengerCreateInfoEXTBuilder<'_> {
let user_data_ptr: *const super::DebugUtilsMessengerUserData = &*self.callback_data;
vk::DebugUtilsMessengerCreateInfoEXT::builder()
.message_severity(self.severity)
.message_type(self.message_type)
.user_data(user_data_ptr as *mut _)
.pfn_user_callback(Some(debug_utils_messenger_callback))
}
}

impl super::Swapchain {
/// # Safety
///
Expand Down Expand Up @@ -297,50 +308,27 @@ impl super::Instance {
raw_instance: ash::Instance,
instance_api_version: u32,
android_sdk_version: u32,
debug_utils_user_data: Option<super::DebugUtilsMessengerUserData>,
debug_utils_create_info: Option<super::DebugUtilsCreateInfo>,
extensions: Vec<&'static CStr>,
flags: wgt::InstanceFlags,
has_nv_optimus: bool,
drop_guard: Option<crate::DropGuard>,
) -> Result<Self, crate::InstanceError> {
log::info!("Instance version: 0x{:x}", instance_api_version);

let debug_utils = if let Some(debug_callback_user_data) = debug_utils_user_data {
let debug_utils = if let Some(debug_utils_create_info) = debug_utils_create_info {
if extensions.contains(&ext::DebugUtils::name()) {
log::info!("Enabling debug utils");
// Move the callback data to the heap, to ensure it will never be
// moved.
let callback_data = Box::new(debug_callback_user_data);

let extension = ext::DebugUtils::new(&entry, &raw_instance);
// having ERROR unconditionally because Vk doesn't like empty flags
let mut severity = vk::DebugUtilsMessageSeverityFlagsEXT::ERROR;
if log::max_level() >= log::LevelFilter::Debug {
severity |= vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE;
}
if log::max_level() >= log::LevelFilter::Info {
severity |= vk::DebugUtilsMessageSeverityFlagsEXT::INFO;
}
if log::max_level() >= log::LevelFilter::Warn {
severity |= vk::DebugUtilsMessageSeverityFlagsEXT::WARNING;
}
let user_data_ptr: *const super::DebugUtilsMessengerUserData = &*callback_data;
let vk_info = vk::DebugUtilsMessengerCreateInfoEXT::builder()
.flags(vk::DebugUtilsMessengerCreateFlagsEXT::empty())
.message_severity(severity)
.message_type(
vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE,
)
.pfn_user_callback(Some(debug_utils_messenger_callback))
.user_data(user_data_ptr as *mut _);
let vk_info = debug_utils_create_info.to_vk_create_info();
let messenger =
unsafe { extension.create_debug_utils_messenger(&vk_info, None) }.unwrap();

Some(super::DebugUtils {
extension,
messenger,
callback_data,
callback_data: debug_utils_create_info.callback_data,
})
} else {
log::info!("Debug utils not enabled: extension not listed");
Expand Down Expand Up @@ -559,10 +547,12 @@ impl super::Instance {
impl Drop for super::InstanceShared {
fn drop(&mut self) {
unsafe {
if let Some(du) = self.debug_utils.take() {
// Keep du alive since destroy_instance may also log
let _du = self.debug_utils.take().map(|du| {
du.extension
.destroy_debug_utils_messenger(du.messenger, None);
}
du
});
if let Some(_drop_guard) = self.drop_guard.take() {
self.raw.destroy_instance(None);
}
Expand Down Expand Up @@ -653,21 +643,52 @@ impl crate::Instance<super::Api> for super::Instance {
let mut layers: Vec<&'static CStr> = Vec::new();

// Request validation layer if asked.
let mut debug_callback_user_data = None;
if desc.flags.contains(wgt::InstanceFlags::VALIDATION) {
let mut debug_utils = None;
if desc.flags.intersects(wgt::InstanceFlags::VALIDATION) {
let validation_layer_name =
CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0").unwrap();
if let Some(layer_properties) = find_layer(&instance_layers, validation_layer_name) {
layers.push(validation_layer_name);
debug_callback_user_data = Some(super::DebugUtilsMessengerUserData {
validation_layer_description: cstr_from_bytes_until_nul(
&layer_properties.description,
)
.unwrap()
.to_owned(),
validation_layer_spec_version: layer_properties.spec_version,
has_obs_layer,
});

if extensions.contains(&ext::DebugUtils::name()) {
// Put the callback data on the heap, to ensure it will never be
// moved.
let callback_data = Box::new(super::DebugUtilsMessengerUserData {
validation_layer_description: cstr_from_bytes_until_nul(
&layer_properties.description,
)
.unwrap()
.to_owned(),
validation_layer_spec_version: layer_properties.spec_version,
has_obs_layer,
});

// having ERROR unconditionally because Vk doesn't like empty flags
let mut severity = vk::DebugUtilsMessageSeverityFlagsEXT::ERROR;
if log::max_level() >= log::LevelFilter::Debug {
severity |= vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE;
}
if log::max_level() >= log::LevelFilter::Info {
severity |= vk::DebugUtilsMessageSeverityFlagsEXT::INFO;
}
if log::max_level() >= log::LevelFilter::Warn {
severity |= vk::DebugUtilsMessageSeverityFlagsEXT::WARNING;
}

let message_type = vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE;

let create_info = super::DebugUtilsCreateInfo {
severity,
message_type,
callback_data,
};

let vk_create_info = create_info.to_vk_create_info().build();

debug_utils = Some((create_info, vk_create_info));
}
} else {
log::warn!(
"InstanceFlags::VALIDATION requested, but unable to find layer: {}",
Expand Down Expand Up @@ -706,23 +727,26 @@ impl crate::Instance<super::Api> for super::Instance {
if extensions.contains(&ash::vk::KhrPortabilityEnumerationFn::name()) {
flags |= vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR;
}

let vk_instance = {
let str_pointers = layers
.iter()
.chain(extensions.iter())
.map(|&s| {
.map(|&s: &&'static _| {
// Safe because `layers` and `extensions` entries have static lifetime.
s.as_ptr()
})
.collect::<Vec<_>>();

let create_info = vk::InstanceCreateInfo::builder()
let mut create_info = vk::InstanceCreateInfo::builder()
.flags(flags)
.application_info(&app_info)
.enabled_layer_names(&str_pointers[..layers.len()])
.enabled_extension_names(&str_pointers[layers.len()..]);

if let Some(&mut (_, ref mut vk_create_info)) = debug_utils.as_mut() {
create_info = create_info.push_next(vk_create_info);
}

unsafe {
profiling::scope!("vkCreateInstance");
entry.create_instance(&create_info, None)
Expand All @@ -741,7 +765,7 @@ impl crate::Instance<super::Api> for super::Instance {
vk_instance,
instance_api_version,
android_sdk_version,
debug_callback_user_data,
debug_utils.map(|(i, _)| i),
extensions,
desc.flags,
has_nv_optimus,
Expand Down
6 changes: 6 additions & 0 deletions wgpu-hal/src/vulkan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ struct DebugUtils {
callback_data: Box<DebugUtilsMessengerUserData>,
}

pub struct DebugUtilsCreateInfo {
severity: vk::DebugUtilsMessageSeverityFlagsEXT,
message_type: vk::DebugUtilsMessageTypeFlagsEXT,
callback_data: Box<DebugUtilsMessengerUserData>,
}

/// User data needed by `instance::debug_utils_messenger_callback`.
///
/// When we create the [`vk::DebugUtilsMessengerEXT`], the `pUserData`
Expand Down

0 comments on commit e7e2f2a

Please sign in to comment.