summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-hal/src/vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wgpu-hal/src/vulkan')
-rw-r--r--third_party/rust/wgpu-hal/src/vulkan/adapter.rs18
-rw-r--r--third_party/rust/wgpu-hal/src/vulkan/instance.rs183
-rw-r--r--third_party/rust/wgpu-hal/src/vulkan/mod.rs34
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
}
}