diff options
Diffstat (limited to 'third_party/rust/wgpu-hal/src/vulkan')
-rw-r--r-- | third_party/rust/wgpu-hal/src/vulkan/adapter.rs | 18 | ||||
-rw-r--r-- | third_party/rust/wgpu-hal/src/vulkan/instance.rs | 183 | ||||
-rw-r--r-- | third_party/rust/wgpu-hal/src/vulkan/mod.rs | 34 |
3 files changed, 168 insertions, 67 deletions
diff --git a/third_party/rust/wgpu-hal/src/vulkan/adapter.rs b/third_party/rust/wgpu-hal/src/vulkan/adapter.rs index 85e620d23c..83b3dfa8e5 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/adapter.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/adapter.rs @@ -189,7 +189,7 @@ impl PhysicalDeviceFeatures { //.shader_clip_distance(requested_features.contains(wgt::Features::SHADER_CLIP_DISTANCE)) //.shader_cull_distance(requested_features.contains(wgt::Features::SHADER_CULL_DISTANCE)) .shader_float64(requested_features.contains(wgt::Features::SHADER_F64)) - //.shader_int64(requested_features.contains(wgt::Features::SHADER_INT64)) + .shader_int64(requested_features.contains(wgt::Features::SHADER_INT64)) .shader_int16(requested_features.contains(wgt::Features::SHADER_I16)) //.shader_resource_residency(requested_features.contains(wgt::Features::SHADER_RESOURCE_RESIDENCY)) .geometry_shader(requested_features.contains(wgt::Features::SHADER_PRIMITIVE_INDEX)) @@ -369,6 +369,7 @@ impl PhysicalDeviceFeatures { | F::ADDRESS_MODE_CLAMP_TO_BORDER | F::ADDRESS_MODE_CLAMP_TO_ZERO | F::TIMESTAMP_QUERY + | F::TIMESTAMP_QUERY_INSIDE_ENCODERS | F::TIMESTAMP_QUERY_INSIDE_PASSES | F::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES | F::CLEAR_TEXTURE; @@ -468,7 +469,7 @@ impl PhysicalDeviceFeatures { //if self.core.shader_clip_distance != 0 { //if self.core.shader_cull_distance != 0 { features.set(F::SHADER_F64, self.core.shader_float64 != 0); - //if self.core.shader_int64 != 0 { + features.set(F::SHADER_INT64, self.core.shader_int64 != 0); features.set(F::SHADER_I16, self.core.shader_int16 != 0); //if caps.supports_extension(vk::KhrSamplerMirrorClampToEdgeFn::name()) { @@ -827,6 +828,11 @@ impl PhysicalDeviceCapabilities { u64::MAX }; + // TODO: programmatically determine this, if possible. It's unclear whether we can + // as of https://github.com/gpuweb/gpuweb/issues/2965#issuecomment-1361315447. + // We could increase the limit when we aren't on a tiled GPU. + let max_color_attachment_bytes_per_sample = 32; + wgt::Limits { max_texture_dimension_1d: limits.max_image_dimension1_d, max_texture_dimension_2d: limits.max_image_dimension2_d, @@ -862,6 +868,10 @@ impl PhysicalDeviceCapabilities { max_inter_stage_shader_components: limits .max_vertex_output_components .min(limits.max_fragment_input_components), + max_color_attachments: limits + .max_color_attachments + .min(crate::MAX_COLOR_ATTACHMENTS as u32), + max_color_attachment_bytes_per_sample, max_compute_workgroup_storage_size: limits.max_compute_shared_memory_size, max_compute_invocations_per_workgroup: limits.max_compute_work_group_invocations, max_compute_workgroup_size_x: max_compute_workgroup_sizes[0], @@ -1444,6 +1454,10 @@ impl super::Adapter { capabilities.push(spv::Capability::RayQueryKHR); } + if features.contains(wgt::Features::SHADER_INT64) { + capabilities.push(spv::Capability::Int64); + } + let mut flags = spv::WriterFlags::empty(); flags.set( spv::WriterFlags::DEBUG, diff --git a/third_party/rust/wgpu-hal/src/vulkan/instance.rs b/third_party/rust/wgpu-hal/src/vulkan/instance.rs index c4ef573461..771938b0b0 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/instance.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/instance.rs @@ -6,6 +6,7 @@ use std::{ thread, }; +use arrayvec::ArrayVec; use ash::{ extensions::{ext, khr}, vk, @@ -34,11 +35,13 @@ unsafe extern "system" fn debug_utils_messenger_callback( // the debug range start and end appear in different command buffers. let khronos_validation_layer = std::ffi::CStr::from_bytes_with_nul(b"Khronos Validation Layer\0").unwrap(); - if user_data.validation_layer_description.as_ref() == khronos_validation_layer - && user_data.validation_layer_spec_version >= vk::make_api_version(0, 1, 3, 240) - && user_data.validation_layer_spec_version <= vk::make_api_version(0, 1, 3, 250) - { - return vk::FALSE; + if let Some(layer_properties) = user_data.validation_layer_properties.as_ref() { + if layer_properties.layer_description.as_ref() == khronos_validation_layer + && layer_properties.layer_spec_version >= vk::make_api_version(0, 1, 3, 240) + && layer_properties.layer_spec_version <= vk::make_api_version(0, 1, 3, 250) + { + return vk::FALSE; + } } } @@ -211,6 +214,22 @@ impl super::Instance { &self.shared } + fn enumerate_instance_extension_properties( + entry: &ash::Entry, + layer_name: Option<&CStr>, + ) -> Result<Vec<vk::ExtensionProperties>, crate::InstanceError> { + let instance_extensions = { + profiling::scope!("vkEnumerateInstanceExtensionProperties"); + entry.enumerate_instance_extension_properties(layer_name) + }; + instance_extensions.map_err(|e| { + crate::InstanceError::with_source( + String::from("enumerate_instance_extension_properties() failed"), + e, + ) + }) + } + /// Return the instance extension names wgpu would like to enable. /// /// Return a vector of the names of instance extensions actually available @@ -229,16 +248,7 @@ impl super::Instance { _instance_api_version: u32, flags: wgt::InstanceFlags, ) -> Result<Vec<&'static CStr>, crate::InstanceError> { - let instance_extensions = { - profiling::scope!("vkEnumerateInstanceExtensionProperties"); - entry.enumerate_instance_extension_properties(None) - }; - let instance_extensions = instance_extensions.map_err(|e| { - crate::InstanceError::with_source( - String::from("enumerate_instance_extension_properties() failed"), - e, - ) - })?; + let instance_extensions = Self::enumerate_instance_extension_properties(entry, None)?; // Check our extensions against the available extensions let mut extensions: Vec<&'static CStr> = Vec::new(); @@ -643,6 +653,31 @@ impl crate::Instance<super::Api> for super::Instance { .find(|inst_layer| cstr_from_bytes_until_nul(&inst_layer.layer_name) == Some(name)) } + let validation_layer_name = + CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0").unwrap(); + let validation_layer_properties = find_layer(&instance_layers, validation_layer_name); + + // Determine if VK_EXT_validation_features is available, so we can enable + // GPU assisted validation and synchronization validation. + let validation_features_are_enabled = if validation_layer_properties.is_some() { + // Get the all the instance extension properties. + let exts = + Self::enumerate_instance_extension_properties(&entry, Some(validation_layer_name))?; + // Convert all the names of the extensions into an iterator of CStrs. + let mut ext_names = exts + .iter() + .filter_map(|ext| cstr_from_bytes_until_nul(&ext.extension_name)); + // Find the validation features extension. + ext_names.any(|ext_name| ext_name == vk::ExtValidationFeaturesFn::name()) + } else { + false + }; + + let should_enable_gpu_based_validation = desc + .flags + .intersects(wgt::InstanceFlags::GPU_BASED_VALIDATION) + && validation_features_are_enabled; + let nv_optimus_layer = CStr::from_bytes_with_nul(b"VK_LAYER_NV_optimus\0").unwrap(); let has_nv_optimus = find_layer(&instance_layers, nv_optimus_layer).is_some(); @@ -651,52 +686,33 @@ impl crate::Instance<super::Api> for super::Instance { let mut layers: Vec<&'static CStr> = Vec::new(); + let has_debug_extension = extensions.contains(&ext::DebugUtils::name()); + let mut debug_user_data = has_debug_extension.then(|| { + // Put the callback data on the heap, to ensure it will never be + // moved. + Box::new(super::DebugUtilsMessengerUserData { + validation_layer_properties: None, + has_obs_layer, + }) + }); + // Request validation layer if asked. - 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) { + if desc.flags.intersects(wgt::InstanceFlags::VALIDATION) + || should_enable_gpu_based_validation + { + if let Some(layer_properties) = validation_layer_properties { layers.push(validation_layer_name); - 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)); + if let Some(debug_user_data) = debug_user_data.as_mut() { + debug_user_data.validation_layer_properties = + Some(super::ValidationLayerProperties { + layer_description: cstr_from_bytes_until_nul( + &layer_properties.description, + ) + .unwrap() + .to_owned(), + layer_spec_version: layer_properties.spec_version, + }); } } else { log::warn!( @@ -705,6 +721,35 @@ impl crate::Instance<super::Api> for super::Instance { ); } } + let mut debug_utils = if let Some(callback_data) = debug_user_data { + // 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(); + + Some((create_info, vk_create_info)) + } else { + None + }; #[cfg(target_os = "android")] let android_sdk_version = { @@ -756,6 +801,28 @@ impl crate::Instance<super::Api> for super::Instance { create_info = create_info.push_next(vk_create_info); } + // Enable explicit validation features if available + let mut validation_features; + let mut validation_feature_list: ArrayVec<_, 3>; + if validation_features_are_enabled { + validation_feature_list = ArrayVec::new(); + + // Always enable synchronization validation + validation_feature_list + .push(vk::ValidationFeatureEnableEXT::SYNCHRONIZATION_VALIDATION); + + // Only enable GPU assisted validation if requested. + if should_enable_gpu_based_validation { + validation_feature_list.push(vk::ValidationFeatureEnableEXT::GPU_ASSISTED); + validation_feature_list + .push(vk::ValidationFeatureEnableEXT::GPU_ASSISTED_RESERVE_BINDING_SLOT); + } + + validation_features = vk::ValidationFeaturesEXT::builder() + .enabled_validation_features(&validation_feature_list); + create_info = create_info.push_next(&mut validation_features); + } + unsafe { profiling::scope!("vkCreateInstance"); entry.create_instance(&create_info, None) diff --git a/third_party/rust/wgpu-hal/src/vulkan/mod.rs b/third_party/rust/wgpu-hal/src/vulkan/mod.rs index 787ebd7267..1f922e83da 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/mod.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/mod.rs @@ -101,17 +101,25 @@ pub struct DebugUtilsCreateInfo { callback_data: Box<DebugUtilsMessengerUserData>, } +#[derive(Debug)] +/// The properties related to the validation layer needed for the +/// DebugUtilsMessenger for their workarounds +struct ValidationLayerProperties { + /// Validation layer description, from `vk::LayerProperties`. + layer_description: std::ffi::CString, + + /// Validation layer specification version, from `vk::LayerProperties`. + layer_spec_version: u32, +} + /// User data needed by `instance::debug_utils_messenger_callback`. /// /// When we create the [`vk::DebugUtilsMessengerEXT`], the `pUserData` /// pointer refers to one of these values. #[derive(Debug)] pub struct DebugUtilsMessengerUserData { - /// Validation layer description, from `vk::LayerProperties`. - validation_layer_description: std::ffi::CString, - - /// Validation layer specification version, from `vk::LayerProperties`. - validation_layer_spec_version: u32, + /// The properties related to the validation layer, if present + validation_layer_properties: Option<ValidationLayerProperties>, /// If the OBS layer is present. OBS never increments the version of their layer, /// so there's no reason to have the version. @@ -724,13 +732,25 @@ impl crate::Queue<Api> for Queue { impl From<vk::Result> for crate::DeviceError { fn from(result: vk::Result) -> Self { + #![allow(unreachable_code)] match result { vk::Result::ERROR_OUT_OF_HOST_MEMORY | vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => { + #[cfg(feature = "oom_panic")] + panic!("Out of memory ({result:?})"); + Self::OutOfMemory } - vk::Result::ERROR_DEVICE_LOST => Self::Lost, + vk::Result::ERROR_DEVICE_LOST => { + #[cfg(feature = "device_lost_panic")] + panic!("Device lost"); + + Self::Lost + } _ => { - log::warn!("Unrecognized device error {:?}", result); + #[cfg(feature = "internal_error_panic")] + panic!("Internal error: {result:?}"); + + log::warn!("Unrecognized device error {result:?}"); Self::Lost } } |