From 23b587246aff9082a544bb51be12b8e9dc5ebc85 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 2 Jul 2021 20:17:06 -0400 Subject: [PATCH] Detailed limits check and error --- Cargo.lock | 2 +- wgpu-core/src/device/mod.rs | 4 +-- wgpu-core/src/instance.rs | 54 ++++++++++++++++++++++++++++++++++--- wgpu-core/src/lib.rs | 11 +------- 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28ba7bab3e..f3222ee74b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1040,7 +1040,7 @@ dependencies = [ [[package]] name = "naga" version = "0.5.0" -source = "git+https://github.com/gfx-rs/naga?rev=68a2efd3c5db62c2c011ccbad84f58be5e539fe3#68a2efd3c5db62c2c011ccbad84f58be5e539fe3" +source = "git+https://github.com/gfx-rs/naga?rev=0b9af95793e319817e74a30601cbcd4bad9bb3e6#0b9af95793e319817e74a30601cbcd4bad9bb3e6" dependencies = [ "bit-set", "bitflags", diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 26d224b5ce..8c1db66e8c 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -8,7 +8,7 @@ use crate::{ track::{BufferState, TextureSelector, TextureState, TrackerSet, UsageConflict}, validation::{self, check_buffer_usage, check_texture_usage}, FastHashMap, Label, LabelHelpers as _, LifeGuard, MultiRefCount, Stored, SubmissionIndex, - DOWNLEVEL_ERROR_WARNING_MESSAGE, + DOWNLEVEL_ERROR_MESSAGE, }; use arrayvec::ArrayVec; @@ -2426,7 +2426,7 @@ pub struct MissingFeatures(pub wgt::Features); #[derive(Clone, Debug, Error)] #[error( "Downlevel flags {0:?} are required but not supported on the device.\n{}", - DOWNLEVEL_ERROR_WARNING_MESSAGE + DOWNLEVEL_ERROR_MESSAGE )] pub struct MissingDownlevelFlags(pub wgt::DownlevelFlags); diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 5849c73a44..42f0ba1153 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -14,6 +14,52 @@ pub type RequestAdapterOptions = wgt::RequestAdapterOptions; type HalInstance = ::Instance; type HalSurface = ::Surface; +#[derive(Clone, Debug, Error)] +#[error("Limit '{name}' value {requested} is better than allowed {allowed}")] +pub struct FailedLimit { + name: &'static str, + requested: u32, + allowed: u32, +} + +fn check_limits(requested: &wgt::Limits, allowed: &wgt::Limits) -> Vec { + use std::cmp::Ordering; + let mut failed = Vec::new(); + + macro_rules! compare { + ($name:ident, $ordering:ident) => { + match requested.$name.cmp(&allowed.$name) { + Ordering::$ordering | Ordering::Equal => (), + _ => failed.push(FailedLimit { + name: stringify!($name), + requested: requested.$name, + allowed: allowed.$name, + }), + } + }; + } + + compare!(max_texture_dimension_1d, Less); + compare!(max_texture_dimension_2d, Less); + compare!(max_texture_dimension_3d, Less); + compare!(max_texture_array_layers, Less); + compare!(max_bind_groups, Less); + compare!(max_dynamic_uniform_buffers_per_pipeline_layout, Less); + compare!(max_dynamic_storage_buffers_per_pipeline_layout, Less); + compare!(max_sampled_textures_per_shader_stage, Less); + compare!(max_samplers_per_shader_stage, Less); + compare!(max_storage_buffers_per_shader_stage, Less); + compare!(max_storage_textures_per_shader_stage, Less); + compare!(max_uniform_buffers_per_shader_stage, Less); + compare!(max_uniform_buffer_binding_size, Less); + compare!(max_storage_buffer_binding_size, Less); + compare!(max_vertex_buffers, Less); + compare!(max_vertex_attributes, Less); + compare!(max_vertex_buffer_array_stride, Less); + compare!(max_push_constant_size, Less); + failed +} + pub struct Instance { #[allow(dead_code)] name: String, @@ -247,8 +293,8 @@ impl Adapter { BIND_BUFFER_ALIGNMENT % caps.alignments.uniform_buffer_offset, "Adapter uniform buffer offset alignment not compatible with WGPU" ); - if caps.limits < desc.limits { - return Err(RequestDeviceError::LimitsExceeded); + if let Some(failed) = check_limits(&desc.limits, &caps.limits).pop() { + return Err(RequestDeviceError::LimitsExceeded(failed)); } Device::new( @@ -295,8 +341,8 @@ pub enum RequestDeviceError { DeviceLost, #[error("device initialization failed due to implementation specific errors")] Internal, - #[error("some of the requested device limits are not supported")] - LimitsExceeded, + #[error(transparent)] + LimitsExceeded(#[from] FailedLimit), #[error("device has no queue supporting graphics")] NoGraphicsQueue, #[error("not enough memory left")] diff --git a/wgpu-core/src/lib.rs b/wgpu-core/src/lib.rs index e8118b86b4..deb45ba4c5 100644 --- a/wgpu-core/src/lib.rs +++ b/wgpu-core/src/lib.rs @@ -81,15 +81,6 @@ impl RefCount { unsafe { self.0.as_ref() }.load(Ordering::Acquire) } - /// This works like `std::mem::drop`, except that it returns a boolean which is true if and only - /// if we deallocated the underlying memory, i.e. if this was the last clone of this `RefCount` - /// to be dropped. This is useful for loom testing because it allows us to verify that we - /// deallocated the underlying memory exactly once. - #[cfg(test)] - fn rich_drop_outer(self) -> bool { - unsafe { std::mem::ManuallyDrop::new(self).rich_drop_inner() } - } - /// This function exists to allow `Self::rich_drop_outer` and `Drop::drop` to share the same /// logic. To use this safely from outside of `Drop::drop`, the calling function must move /// `Self` into a `ManuallyDrop`. @@ -191,7 +182,7 @@ support enough features to be a fully compliant implementation of WebGPU. A subs If you are running this program on native and not in a browser and wish to limit the features you use to the supported subset, \ call Adapter::downlevel_properties or Device::downlevel_properties to get a listing of the features the current \ platform supports."; -const DOWNLEVEL_ERROR_WARNING_MESSAGE: &str = "This is not an invalid use of WebGPU: the underlying API or device does not \ +const DOWNLEVEL_ERROR_MESSAGE: &str = "This is not an invalid use of WebGPU: the underlying API or device does not \ support enough features to be a fully compliant implementation. A subset of the features can still be used. \ If you are running this program on native and not in a browser and wish to work around this issue, call \ Adapter::downlevel_properties or Device::downlevel_properties to get a listing of the features the current \