Skip to content

Commit ef5db05

Browse files
committed
fix(types): Check that with_limits! is exhaustive
1 parent 5574c21 commit ef5db05

File tree

2 files changed

+137
-64
lines changed

2 files changed

+137
-64
lines changed

wgpu-hal/src/noop/mod.rs

Lines changed: 1 addition & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -154,71 +154,8 @@ pub fn adapter_info() -> wgt::AdapterInfo {
154154
/// This is used in the test harness to construct capabilities
155155
/// of the noop backend without actually initializing wgpu.
156156
pub const CAPABILITIES: crate::Capabilities = {
157-
/// Guaranteed to be no bigger than isize::MAX which is the maximum size of an allocation,
158-
/// except on 16-bit platforms which we certainly don’t fit in.
159-
const ALLOC_MAX_U32: u32 = i32::MAX as u32;
160-
/// Guaranteed to be no bigger than isize::MAX which is the maximum size of an allocation,
161-
/// except on 16-bit platforms which we certainly don’t fit in.
162-
const ALLOC_MAX_U64: u64 = i32::MAX as u64;
163-
164157
crate::Capabilities {
165-
limits: wgt::Limits {
166-
// All maximally permissive
167-
max_texture_dimension_1d: ALLOC_MAX_U32,
168-
max_texture_dimension_2d: ALLOC_MAX_U32,
169-
max_texture_dimension_3d: ALLOC_MAX_U32,
170-
max_texture_array_layers: ALLOC_MAX_U32,
171-
max_bind_groups: ALLOC_MAX_U32,
172-
max_bindings_per_bind_group: ALLOC_MAX_U32,
173-
max_dynamic_uniform_buffers_per_pipeline_layout: ALLOC_MAX_U32,
174-
max_dynamic_storage_buffers_per_pipeline_layout: ALLOC_MAX_U32,
175-
max_sampled_textures_per_shader_stage: ALLOC_MAX_U32,
176-
max_samplers_per_shader_stage: ALLOC_MAX_U32,
177-
max_storage_buffers_per_shader_stage: ALLOC_MAX_U32,
178-
max_storage_textures_per_shader_stage: ALLOC_MAX_U32,
179-
max_uniform_buffers_per_shader_stage: ALLOC_MAX_U32,
180-
max_binding_array_elements_per_shader_stage: ALLOC_MAX_U32,
181-
max_binding_array_sampler_elements_per_shader_stage: ALLOC_MAX_U32,
182-
max_binding_array_acceleration_structure_elements_per_shader_stage: ALLOC_MAX_U32,
183-
max_uniform_buffer_binding_size: ALLOC_MAX_U64,
184-
max_storage_buffer_binding_size: ALLOC_MAX_U64,
185-
max_vertex_buffers: ALLOC_MAX_U32,
186-
max_buffer_size: ALLOC_MAX_U64,
187-
max_vertex_attributes: ALLOC_MAX_U32,
188-
max_vertex_buffer_array_stride: ALLOC_MAX_U32,
189-
max_inter_stage_shader_variables: ALLOC_MAX_U32,
190-
min_uniform_buffer_offset_alignment: 1,
191-
min_storage_buffer_offset_alignment: 1,
192-
max_color_attachments: ALLOC_MAX_U32,
193-
max_color_attachment_bytes_per_sample: ALLOC_MAX_U32,
194-
max_compute_workgroup_storage_size: ALLOC_MAX_U32,
195-
max_compute_invocations_per_workgroup: ALLOC_MAX_U32,
196-
max_compute_workgroup_size_x: ALLOC_MAX_U32,
197-
max_compute_workgroup_size_y: ALLOC_MAX_U32,
198-
max_compute_workgroup_size_z: ALLOC_MAX_U32,
199-
max_compute_workgroups_per_dimension: ALLOC_MAX_U32,
200-
max_immediate_size: ALLOC_MAX_U32,
201-
max_non_sampler_bindings: ALLOC_MAX_U32,
202-
203-
max_task_mesh_workgroup_total_count: ALLOC_MAX_U32,
204-
max_task_mesh_workgroups_per_dimension: ALLOC_MAX_U32,
205-
max_task_invocations_per_workgroup: ALLOC_MAX_U32,
206-
max_task_invocations_per_dimension: ALLOC_MAX_U32,
207-
max_mesh_invocations_per_workgroup: ALLOC_MAX_U32,
208-
max_mesh_invocations_per_dimension: ALLOC_MAX_U32,
209-
max_task_payload_size: ALLOC_MAX_U32,
210-
max_mesh_output_vertices: ALLOC_MAX_U32,
211-
max_mesh_output_primitives: ALLOC_MAX_U32,
212-
max_mesh_output_layers: ALLOC_MAX_U32,
213-
max_mesh_multiview_view_count: ALLOC_MAX_U32,
214-
215-
max_blas_primitive_count: ALLOC_MAX_U32,
216-
max_blas_geometry_count: ALLOC_MAX_U32,
217-
max_tlas_instance_count: ALLOC_MAX_U32,
218-
max_acceleration_structures_per_shader_stage: ALLOC_MAX_U32,
219-
220-
max_multiview_view_count: ALLOC_MAX_U32,
221-
},
158+
limits: wgt::Limits::unlimited(),
222159
alignments: crate::Alignments {
223160
// All maximally permissive
224161
buffer_copy_offset: wgt::BufferSize::MIN,

wgpu-types/src/limits.rs

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ macro_rules! with_limits {
4242
max_binding_array_acceleration_structure_elements_per_shader_stage,
4343
Ordering::Less
4444
);
45+
$macro_name!(
46+
max_binding_array_sampler_elements_per_shader_stage,
47+
Ordering::Less
48+
);
49+
4550
$macro_name!(max_uniform_buffer_binding_size, Ordering::Less);
4651
$macro_name!(max_storage_buffer_binding_size, Ordering::Less);
4752
$macro_name!(max_vertex_buffers, Ordering::Less);
@@ -79,6 +84,7 @@ macro_rules! with_limits {
7984
$macro_name!(max_blas_primitive_count, Ordering::Less);
8085
$macro_name!(max_blas_geometry_count, Ordering::Less);
8186
$macro_name!(max_tlas_instance_count, Ordering::Less);
87+
$macro_name!(max_acceleration_structures_per_shader_stage, Ordering::Less);
8288

8389
$macro_name!(max_multiview_view_count, Ordering::Less);
8490
};
@@ -594,6 +600,78 @@ impl Limits {
594600
}
595601
}
596602

603+
/// Sets each limit to `i32::MAX` (or 1, in the case of lower-is-better limits).
604+
///
605+
/// These values do not reflect the capabilities of any actual device. They are
606+
/// used by the noop backend, and by the test that makes sure `with_limits!` is
607+
/// exhaustive.
608+
#[must_use]
609+
pub const fn unlimited() -> Self {
610+
/// Guaranteed to be no bigger than isize::MAX which is the maximum size of an allocation,
611+
/// except on 16-bit platforms which we certainly don’t fit in.
612+
const ALLOC_MAX_U32: u32 = i32::MAX as u32;
613+
/// Guaranteed to be no bigger than isize::MAX which is the maximum size of an allocation,
614+
/// except on 16-bit platforms which we certainly don’t fit in.
615+
const ALLOC_MAX_U64: u64 = i32::MAX as u64;
616+
617+
Self {
618+
max_texture_dimension_1d: ALLOC_MAX_U32,
619+
max_texture_dimension_2d: ALLOC_MAX_U32,
620+
max_texture_dimension_3d: ALLOC_MAX_U32,
621+
max_texture_array_layers: ALLOC_MAX_U32,
622+
max_bind_groups: ALLOC_MAX_U32,
623+
max_bindings_per_bind_group: ALLOC_MAX_U32,
624+
max_dynamic_uniform_buffers_per_pipeline_layout: ALLOC_MAX_U32,
625+
max_dynamic_storage_buffers_per_pipeline_layout: ALLOC_MAX_U32,
626+
max_sampled_textures_per_shader_stage: ALLOC_MAX_U32,
627+
max_samplers_per_shader_stage: ALLOC_MAX_U32,
628+
max_storage_buffers_per_shader_stage: ALLOC_MAX_U32,
629+
max_storage_textures_per_shader_stage: ALLOC_MAX_U32,
630+
max_uniform_buffers_per_shader_stage: ALLOC_MAX_U32,
631+
max_binding_array_elements_per_shader_stage: ALLOC_MAX_U32,
632+
max_binding_array_sampler_elements_per_shader_stage: ALLOC_MAX_U32,
633+
max_binding_array_acceleration_structure_elements_per_shader_stage: ALLOC_MAX_U32,
634+
max_uniform_buffer_binding_size: ALLOC_MAX_U64,
635+
max_storage_buffer_binding_size: ALLOC_MAX_U64,
636+
max_vertex_buffers: ALLOC_MAX_U32,
637+
max_buffer_size: ALLOC_MAX_U64,
638+
max_vertex_attributes: ALLOC_MAX_U32,
639+
max_vertex_buffer_array_stride: ALLOC_MAX_U32,
640+
max_inter_stage_shader_variables: ALLOC_MAX_U32,
641+
min_uniform_buffer_offset_alignment: 1,
642+
min_storage_buffer_offset_alignment: 1,
643+
max_color_attachments: ALLOC_MAX_U32,
644+
max_color_attachment_bytes_per_sample: ALLOC_MAX_U32,
645+
max_compute_workgroup_storage_size: ALLOC_MAX_U32,
646+
max_compute_invocations_per_workgroup: ALLOC_MAX_U32,
647+
max_compute_workgroup_size_x: ALLOC_MAX_U32,
648+
max_compute_workgroup_size_y: ALLOC_MAX_U32,
649+
max_compute_workgroup_size_z: ALLOC_MAX_U32,
650+
max_compute_workgroups_per_dimension: ALLOC_MAX_U32,
651+
max_immediate_size: ALLOC_MAX_U32,
652+
max_non_sampler_bindings: ALLOC_MAX_U32,
653+
654+
max_task_mesh_workgroup_total_count: ALLOC_MAX_U32,
655+
max_task_mesh_workgroups_per_dimension: ALLOC_MAX_U32,
656+
max_task_invocations_per_workgroup: ALLOC_MAX_U32,
657+
max_task_invocations_per_dimension: ALLOC_MAX_U32,
658+
max_mesh_invocations_per_workgroup: ALLOC_MAX_U32,
659+
max_mesh_invocations_per_dimension: ALLOC_MAX_U32,
660+
max_task_payload_size: ALLOC_MAX_U32,
661+
max_mesh_output_vertices: ALLOC_MAX_U32,
662+
max_mesh_output_primitives: ALLOC_MAX_U32,
663+
max_mesh_output_layers: ALLOC_MAX_U32,
664+
max_mesh_multiview_view_count: ALLOC_MAX_U32,
665+
666+
max_blas_primitive_count: ALLOC_MAX_U32,
667+
max_blas_geometry_count: ALLOC_MAX_U32,
668+
max_tlas_instance_count: ALLOC_MAX_U32,
669+
max_acceleration_structures_per_shader_stage: ALLOC_MAX_U32,
670+
671+
max_multiview_view_count: ALLOC_MAX_U32,
672+
}
673+
}
674+
597675
/// Modify the current limits to use the resolution limits of the other.
598676
///
599677
/// This is useful because the swapchain might need to be larger than any other image in the application.
@@ -991,3 +1069,61 @@ pub enum ShaderModel {
9911069
/// WebGPU supports shader module 5.
9921070
Sm5,
9931071
}
1072+
1073+
#[cfg(test)]
1074+
mod tests {
1075+
use super::*;
1076+
use std::{format, string::String, vec::Vec};
1077+
1078+
fn side_by_side(left: &str, right: &str) -> String {
1079+
let left_lines: Vec<&str> = left.lines().map(str::trim).collect();
1080+
let right_lines: Vec<&str> = right.lines().map(str::trim).collect();
1081+
let max_lines = left_lines.len().max(right_lines.len());
1082+
let diffs: Vec<(&str, &str)> = (0..max_lines)
1083+
.map(|i| {
1084+
let l = *left_lines.get(i).unwrap_or(&"");
1085+
let r = *right_lines.get(i).unwrap_or(&"");
1086+
(l, r)
1087+
})
1088+
.filter(|(l, r)| l != r)
1089+
.collect();
1090+
let left_width = diffs.iter().map(|(l, _)| l.len()).max().unwrap_or(0);
1091+
let mut out = String::new();
1092+
for (l, r) in &diffs {
1093+
out += &format!("{:<width$} | {}\n", l, r, width = left_width);
1094+
}
1095+
out
1096+
}
1097+
1098+
#[test]
1099+
fn with_limits_exhaustive() {
1100+
// Check that all limits are included in `with_limits!`, by using it to
1101+
// replicate `Limits::unlimited()`.
1102+
let mut limits = Limits::default();
1103+
1104+
macro_rules! set_to_max {
1105+
($name:ident, $ordering:expr) => {
1106+
if $ordering == Ordering::Less {
1107+
limits.$name = i32::MAX as _;
1108+
} else {
1109+
limits.$name = 1;
1110+
}
1111+
};
1112+
}
1113+
1114+
with_limits!(set_to_max);
1115+
1116+
assert_eq!(
1117+
limits,
1118+
Limits::unlimited(),
1119+
"with_limits! did not replicate Limits::unlimited():\n{}",
1120+
side_by_side(
1121+
&format!("with_limits!\n------------\n{:#?}", limits),
1122+
&format!(
1123+
"Limits::unlimited()\n-------------------\n{:#?}",
1124+
Limits::unlimited()
1125+
),
1126+
)
1127+
);
1128+
}
1129+
}

0 commit comments

Comments
 (0)