@@ -16,6 +16,7 @@ extern crate alloc;
16
16
17
17
use alloc:: borrow:: Cow ;
18
18
use alloc:: { string:: String , vec, vec:: Vec } ;
19
+ use core:: cmp:: Ordering ;
19
20
use core:: {
20
21
fmt,
21
22
hash:: { Hash , Hasher } ,
@@ -459,6 +460,71 @@ impl fmt::Display for RequestAdapterError {
459
460
}
460
461
}
461
462
463
+ /// Invoke a macro for each of the limits.
464
+ ///
465
+ /// The supplied macro should take two arguments. The first is a limit name, as
466
+ /// an identifier, typically used to access a member of `struct Limits`. The
467
+ /// second is `Ordering::Less` if valid values are less than the limit (the
468
+ /// common case), or `Ordering::Greater` if valid values are more than the limit
469
+ /// (for limits like alignments, which are minima instead of maxima).
470
+ macro_rules! with_limits {
471
+ ( $macro_name: ident) => {
472
+ $macro_name!( max_texture_dimension_1d, Ordering :: Less ) ;
473
+ $macro_name!( max_texture_dimension_1d, Ordering :: Less ) ;
474
+ $macro_name!( max_texture_dimension_2d, Ordering :: Less ) ;
475
+ $macro_name!( max_texture_dimension_3d, Ordering :: Less ) ;
476
+ $macro_name!( max_texture_array_layers, Ordering :: Less ) ;
477
+ $macro_name!( max_bind_groups, Ordering :: Less ) ;
478
+ $macro_name!( max_bindings_per_bind_group, Ordering :: Less ) ;
479
+ $macro_name!(
480
+ max_dynamic_uniform_buffers_per_pipeline_layout,
481
+ Ordering :: Less
482
+ ) ;
483
+ $macro_name!(
484
+ max_dynamic_storage_buffers_per_pipeline_layout,
485
+ Ordering :: Less
486
+ ) ;
487
+ $macro_name!( max_sampled_textures_per_shader_stage, Ordering :: Less ) ;
488
+ $macro_name!( max_samplers_per_shader_stage, Ordering :: Less ) ;
489
+ $macro_name!( max_storage_buffers_per_shader_stage, Ordering :: Less ) ;
490
+ $macro_name!( max_storage_textures_per_shader_stage, Ordering :: Less ) ;
491
+ $macro_name!( max_uniform_buffers_per_shader_stage, Ordering :: Less ) ;
492
+ $macro_name!( max_binding_array_elements_per_shader_stage, Ordering :: Less ) ;
493
+ $macro_name!( max_uniform_buffer_binding_size, Ordering :: Less ) ;
494
+ $macro_name!( max_storage_buffer_binding_size, Ordering :: Less ) ;
495
+ $macro_name!( max_vertex_buffers, Ordering :: Less ) ;
496
+ $macro_name!( max_buffer_size, Ordering :: Less ) ;
497
+ $macro_name!( max_vertex_attributes, Ordering :: Less ) ;
498
+ $macro_name!( max_vertex_buffer_array_stride, Ordering :: Less ) ;
499
+ $macro_name!( min_uniform_buffer_offset_alignment, Ordering :: Greater ) ;
500
+ $macro_name!( min_storage_buffer_offset_alignment, Ordering :: Greater ) ;
501
+ $macro_name!( max_inter_stage_shader_components, Ordering :: Less ) ;
502
+ $macro_name!( max_color_attachments, Ordering :: Less ) ;
503
+ $macro_name!( max_color_attachment_bytes_per_sample, Ordering :: Less ) ;
504
+ $macro_name!( max_compute_workgroup_storage_size, Ordering :: Less ) ;
505
+ $macro_name!( max_compute_invocations_per_workgroup, Ordering :: Less ) ;
506
+ $macro_name!( max_compute_workgroup_size_x, Ordering :: Less ) ;
507
+ $macro_name!( max_compute_workgroup_size_y, Ordering :: Less ) ;
508
+ $macro_name!( max_compute_workgroup_size_z, Ordering :: Less ) ;
509
+ $macro_name!( max_compute_workgroups_per_dimension, Ordering :: Less ) ;
510
+
511
+ $macro_name!( min_subgroup_size, Ordering :: Greater ) ;
512
+ $macro_name!( max_subgroup_size, Ordering :: Less ) ;
513
+
514
+ $macro_name!( max_push_constant_size, Ordering :: Less ) ;
515
+ $macro_name!( max_non_sampler_bindings, Ordering :: Less ) ;
516
+
517
+ $macro_name!( max_task_workgroup_total_count, Ordering :: Less ) ;
518
+ $macro_name!( max_task_workgroups_per_dimension, Ordering :: Less ) ;
519
+ $macro_name!( max_mesh_multiview_count, Ordering :: Less ) ;
520
+ $macro_name!( max_mesh_output_layers, Ordering :: Less ) ;
521
+
522
+ $macro_name!( max_blas_primitive_count, Ordering :: Less ) ;
523
+ $macro_name!( max_blas_geometry_count, Ordering :: Less ) ;
524
+ $macro_name!( max_tlas_instance_count, Ordering :: Less ) ;
525
+ } ;
526
+ }
527
+
462
528
/// Represents the sets of limits an adapter/device supports.
463
529
///
464
530
/// We provide three different defaults.
@@ -1015,68 +1081,59 @@ impl Limits {
1015
1081
fatal : bool ,
1016
1082
mut fail_fn : impl FnMut ( & ' static str , u64 , u64 ) ,
1017
1083
) {
1018
- use core:: cmp:: Ordering ;
1019
-
1020
- macro_rules! compare {
1021
- ( $name: ident, $ordering: ident) => {
1022
- match self . $name. cmp( & allowed. $name) {
1023
- Ordering :: $ordering | Ordering :: Equal => ( ) ,
1024
- _ => {
1025
- fail_fn( stringify!( $name) , self . $name as u64 , allowed. $name as u64 ) ;
1026
- if fatal {
1027
- return ;
1028
- }
1084
+ macro_rules! check_with_fail_fn {
1085
+ ( $name: ident, $ordering: expr) => {
1086
+ let invalid_ord = $ordering. reverse( ) ;
1087
+ // In the case of `min_subgroup_size`, requesting a value of
1088
+ // zero means "I'm not going to use subgroups", so we have to
1089
+ // special case that. If any of our minimum limits could
1090
+ // meaningfully go all the way to zero, that would conflict with
1091
+ // this.
1092
+ if self . $name != 0 && self . $name. cmp( & allowed. $name) == invalid_ord {
1093
+ fail_fn( stringify!( $name) , self . $name as u64 , allowed. $name as u64 ) ;
1094
+ if fatal {
1095
+ return ;
1029
1096
}
1030
1097
}
1031
1098
} ;
1032
1099
}
1033
1100
1034
- compare ! ( max_texture_dimension_1d, Less ) ;
1035
- compare ! ( max_texture_dimension_2d, Less ) ;
1036
- compare ! ( max_texture_dimension_3d, Less ) ;
1037
- compare ! ( max_texture_array_layers, Less ) ;
1038
- compare ! ( max_bind_groups, Less ) ;
1039
- compare ! ( max_bindings_per_bind_group, Less ) ;
1040
- compare ! ( max_dynamic_uniform_buffers_per_pipeline_layout, Less ) ;
1041
- compare ! ( max_dynamic_storage_buffers_per_pipeline_layout, Less ) ;
1042
- compare ! ( max_sampled_textures_per_shader_stage, Less ) ;
1043
- compare ! ( max_samplers_per_shader_stage, Less ) ;
1044
- compare ! ( max_storage_buffers_per_shader_stage, Less ) ;
1045
- compare ! ( max_storage_textures_per_shader_stage, Less ) ;
1046
- compare ! ( max_uniform_buffers_per_shader_stage, Less ) ;
1047
- compare ! ( max_binding_array_elements_per_shader_stage, Less ) ;
1048
- compare ! ( max_uniform_buffer_binding_size, Less ) ;
1049
- compare ! ( max_storage_buffer_binding_size, Less ) ;
1050
- compare ! ( max_vertex_buffers, Less ) ;
1051
- compare ! ( max_buffer_size, Less ) ;
1052
- compare ! ( max_vertex_attributes, Less ) ;
1053
- compare ! ( max_vertex_buffer_array_stride, Less ) ;
1054
- compare ! ( min_uniform_buffer_offset_alignment, Greater ) ;
1055
- compare ! ( min_storage_buffer_offset_alignment, Greater ) ;
1056
- compare ! ( max_inter_stage_shader_components, Less ) ;
1057
- compare ! ( max_color_attachments, Less ) ;
1058
- compare ! ( max_color_attachment_bytes_per_sample, Less ) ;
1059
- compare ! ( max_compute_workgroup_storage_size, Less ) ;
1060
- compare ! ( max_compute_invocations_per_workgroup, Less ) ;
1061
- compare ! ( max_compute_workgroup_size_x, Less ) ;
1062
- compare ! ( max_compute_workgroup_size_y, Less ) ;
1063
- compare ! ( max_compute_workgroup_size_z, Less ) ;
1064
- compare ! ( max_compute_workgroups_per_dimension, Less ) ;
1065
- if self . min_subgroup_size > 0 && self . max_subgroup_size > 0 {
1066
- compare ! ( min_subgroup_size, Greater ) ;
1067
- compare ! ( max_subgroup_size, Less ) ;
1101
+ if self . min_subgroup_size > self . max_subgroup_size {
1102
+ fail_fn (
1103
+ "max_subgroup_size" ,
1104
+ self . min_subgroup_size as u64 ,
1105
+ allowed. min_subgroup_size as u64 ,
1106
+ ) ;
1107
+ }
1108
+ with_limits ! ( check_with_fail_fn) ;
1109
+ }
1110
+
1111
+ /// For each limit in `other` that is better than the value in `self`,
1112
+ /// replace the value in `self` with the value from `other`.
1113
+ ///
1114
+ /// A request for a limit value less than the WebGPU-specified default must
1115
+ /// be ignored. This function is used to clamp such requests to the default
1116
+ /// value.
1117
+ ///
1118
+ /// This is not what you want to clamp a request that otherwise might be
1119
+ /// asking for something beyond the supported limits.
1120
+ #[ must_use]
1121
+ pub fn or_better_values_from ( mut self , other : & Self ) -> Self {
1122
+ macro_rules! or_better_value_from {
1123
+ ( $name: ident, $ordering: expr) => {
1124
+ match $ordering {
1125
+ // Limits that are maximum values (most of them)
1126
+ Ordering :: Less => self . $name = self . $name. max( other. $name) ,
1127
+ // Limits that are minimum values
1128
+ Ordering :: Greater => self . $name = self . $name. min( other. $name) ,
1129
+ Ordering :: Equal => unreachable!( ) ,
1130
+ }
1131
+ } ;
1068
1132
}
1069
- compare ! ( max_push_constant_size, Less ) ;
1070
- compare ! ( max_non_sampler_bindings, Less ) ;
1071
1133
1072
- compare ! ( max_task_workgroup_total_count, Less ) ;
1073
- compare ! ( max_task_workgroups_per_dimension, Less ) ;
1074
- compare ! ( max_mesh_multiview_count, Less ) ;
1075
- compare ! ( max_mesh_output_layers, Less ) ;
1134
+ with_limits ! ( or_better_value_from) ;
1076
1135
1077
- compare ! ( max_blas_primitive_count, Less ) ;
1078
- compare ! ( max_blas_geometry_count, Less ) ;
1079
- compare ! ( max_tlas_instance_count, Less ) ;
1136
+ self
1080
1137
}
1081
1138
}
1082
1139
0 commit comments