From 238e6b74eece8a3dc13c2678ca8b0bc2c40c88f3 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Tue, 7 Jul 2020 15:57:37 -0400 Subject: [PATCH] Populate limits struct --- wgpu-core/src/instance.rs | 45 +++++++++++++++++++++++++++++++++------ wgpu-types/src/lib.rs | 28 ++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 9b670de05d..81aae6bbeb 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -162,9 +162,44 @@ impl Adapter { let adapter_limits = raw.physical_device.limits(); + let default_limits = wgt::Limits::default(); + + // All these casts to u32 are safe as the underlying vulkan types are u32s. + // If another backend provides larger limits than u32, we need to clamp them to u32::MAX. + // TODO: fix all gfx-hal backends to produce limits we care about, and remove .max let limits = wgt::Limits { max_bind_groups: (adapter_limits.max_bound_descriptor_sets as u32) - .min(MAX_BIND_GROUPS as u32), + .min(MAX_BIND_GROUPS as u32) + .max(default_limits.max_bind_groups), + max_dynamic_uniform_buffers_per_pipeline_layout: (adapter_limits + .max_descriptor_set_uniform_buffers_dynamic + as u32) + .max(default_limits.max_dynamic_uniform_buffers_per_pipeline_layout), + max_dynamic_storage_buffers_per_pipeline_layout: (adapter_limits + .max_descriptor_set_storage_buffers_dynamic + as u32) + .max(default_limits.max_dynamic_storage_buffers_per_pipeline_layout), + max_sampled_textures_per_shader_stage: (adapter_limits + .max_per_stage_descriptor_sampled_images + as u32) + .max(default_limits.max_sampled_textures_per_shader_stage), + max_samplers_per_shader_stage: (adapter_limits.max_per_stage_descriptor_samplers + as u32) + .max(default_limits.max_samplers_per_shader_stage), + max_storage_buffers_per_shader_stage: (adapter_limits + .max_per_stage_descriptor_storage_buffers + as u32) + .max(default_limits.max_storage_buffers_per_shader_stage), + max_storage_textures_per_shader_stage: (adapter_limits + .max_per_stage_descriptor_storage_images + as u32) + .max(default_limits.max_storage_textures_per_shader_stage), + max_uniform_buffers_per_shader_stage: (adapter_limits + .max_per_stage_descriptor_uniform_buffers + as u32) + .max(default_limits.max_uniform_buffers_per_shader_stage), + max_uniform_buffer_binding_size: (adapter_limits.max_uniform_buffer_range as u32) + .max(default_limits.max_uniform_buffer_binding_size), _non_exhaustive: unsafe { wgt::NonExhaustive::new() }, }; @@ -670,12 +705,8 @@ impl Global { BIND_BUFFER_ALIGNMENT % limits.min_uniform_buffer_offset_alignment, "Adapter uniform buffer offset alignment not compatible with WGPU" ); - if limits.max_bound_descriptor_sets == 0 { - log::warn!("max_bind_groups limit is missing"); - } else { - if adapter.limits.max_bind_groups < desc.limits.max_bind_groups { - return Err(RequestDeviceError::LimitsExceeded); - } + if adapter.limits < desc.limits { + return Err(RequestDeviceError::LimitsExceeded); } let mem_props = phd.memory_properties(); diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 6eab6ec807..af61e65f06 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -114,7 +114,7 @@ impl From for BackendBit { /// } /// ``` #[doc(hidden)] -#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)] +#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "trace", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct NonExhaustive(()); @@ -252,12 +252,28 @@ bitflags::bitflags! { /// /// See also: https://gpuweb.github.io/gpuweb/#dictdef-gpulimits #[repr(C)] -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "trace", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct Limits { /// Amount of bind groups that can be attached to a pipeline at the same time. Defaults to 4. Higher is "better". pub max_bind_groups: u32, + /// Amount of uniform buffer bindings that can be dynamic in a single pipeline. Defaults to 8. Higher is "better". + pub max_dynamic_uniform_buffers_per_pipeline_layout: u32, + /// Amount of storage buffer bindings that can be dynamic in a single pipeline. Defaults to 4. Higher is "better". + pub max_dynamic_storage_buffers_per_pipeline_layout: u32, + /// Amount of sampled textures visible in a single shader stage. Defaults to 16. Higher is "better". + pub max_sampled_textures_per_shader_stage: u32, + /// Amount of samplers visible in a single shader stage. Defaults to 16. Higher is "better". + pub max_samplers_per_shader_stage: u32, + /// Amount of storage buffers visible in a single shader stage. Defaults to 4. Higher is "better". + pub max_storage_buffers_per_shader_stage: u32, + /// Amount of storage textures visible in a single shader stage. Defaults to 4. Higher is "better". + pub max_storage_textures_per_shader_stage: u32, + /// Amount of uniform buffers visible in a single shader stage. Defaults to 12. Higher is "better". + pub max_uniform_buffers_per_shader_stage: u32, + /// Maximum size in bytes of a binding to a uniform buffer. Defaults to 16384. Higher is "better". + pub max_uniform_buffer_binding_size: u32, /// This struct must be partially constructed from its default. pub _non_exhaustive: NonExhaustive, } @@ -266,6 +282,14 @@ impl Default for Limits { fn default() -> Self { Limits { max_bind_groups: 4, + max_dynamic_uniform_buffers_per_pipeline_layout: 8, + max_dynamic_storage_buffers_per_pipeline_layout: 4, + max_sampled_textures_per_shader_stage: 16, + max_samplers_per_shader_stage: 16, + max_storage_buffers_per_shader_stage: 4, + max_storage_textures_per_shader_stage: 4, + max_uniform_buffers_per_shader_stage: 12, + max_uniform_buffer_binding_size: 16384, _non_exhaustive: unsafe { NonExhaustive::new() }, } }