@@ -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