Skip to content

Commit 96840d7

Browse files
refactor(core): make with_limits!(…) exhaustive
1 parent d29383b commit 96840d7

3 files changed

Lines changed: 85 additions & 73 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wgpu-types/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ web = ["dep:js-sys", "dep:web-sys"]
5252
bitflags.workspace = true
5353
bytemuck = { workspace = true, features = ["derive"] }
5454
log.workspace = true
55+
macro_rules_attribute = { workspace = true }
5556
raw-window-handle.workspace = true
5657
serde = { workspace = true, default-features = false, features = [
5758
"alloc",

wgpu-types/src/limits.rs

Lines changed: 83 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,85 +2,43 @@
22
33
use core::cmp::Ordering;
44

5+
use macro_rules_attribute::macro_rules_derive;
6+
57
#[cfg(any(feature = "serde", test))]
68
use serde::{Deserialize, Serialize};
79

810
#[cfg(doc)]
911
use crate::{Features, TextureFormat};
1012

11-
/// Invoke a macro for each of the limits.
12-
///
13-
/// The supplied macro should take two arguments. The first is a limit name, as
14-
/// an identifier, typically used to access a member of `struct Limits`. The
15-
/// second is `Ordering::Less` if valid values are less than the limit (the
16-
/// common case), or `Ordering::Greater` if valid values are more than the limit
17-
/// (for limits like alignments, which are minima instead of maxima).
18-
macro_rules! with_limits {
19-
($macro_name:ident) => {
20-
$macro_name!(max_texture_dimension_1d, Ordering::Less);
21-
$macro_name!(max_texture_dimension_1d, Ordering::Less);
22-
$macro_name!(max_texture_dimension_2d, Ordering::Less);
23-
$macro_name!(max_texture_dimension_3d, Ordering::Less);
24-
$macro_name!(max_texture_array_layers, Ordering::Less);
25-
$macro_name!(max_bind_groups, Ordering::Less);
26-
$macro_name!(max_bindings_per_bind_group, Ordering::Less);
27-
$macro_name!(
28-
max_dynamic_uniform_buffers_per_pipeline_layout,
29-
Ordering::Less
30-
);
31-
$macro_name!(
32-
max_dynamic_storage_buffers_per_pipeline_layout,
33-
Ordering::Less
34-
);
35-
$macro_name!(max_sampled_textures_per_shader_stage, Ordering::Less);
36-
$macro_name!(max_samplers_per_shader_stage, Ordering::Less);
37-
$macro_name!(max_storage_buffers_per_shader_stage, Ordering::Less);
38-
$macro_name!(max_storage_textures_per_shader_stage, Ordering::Less);
39-
$macro_name!(max_uniform_buffers_per_shader_stage, Ordering::Less);
40-
$macro_name!(max_binding_array_elements_per_shader_stage, Ordering::Less);
41-
$macro_name!(
42-
max_binding_array_acceleration_structure_elements_per_shader_stage,
43-
Ordering::Less
44-
);
45-
$macro_name!(max_uniform_buffer_binding_size, Ordering::Less);
46-
$macro_name!(max_storage_buffer_binding_size, Ordering::Less);
47-
$macro_name!(max_vertex_buffers, Ordering::Less);
48-
$macro_name!(max_buffer_size, Ordering::Less);
49-
$macro_name!(max_vertex_attributes, Ordering::Less);
50-
$macro_name!(max_vertex_buffer_array_stride, Ordering::Less);
51-
$macro_name!(max_inter_stage_shader_variables, Ordering::Less);
52-
$macro_name!(min_uniform_buffer_offset_alignment, Ordering::Greater);
53-
$macro_name!(min_storage_buffer_offset_alignment, Ordering::Greater);
54-
$macro_name!(max_color_attachments, Ordering::Less);
55-
$macro_name!(max_color_attachment_bytes_per_sample, Ordering::Less);
56-
$macro_name!(max_compute_workgroup_storage_size, Ordering::Less);
57-
$macro_name!(max_compute_invocations_per_workgroup, Ordering::Less);
58-
$macro_name!(max_compute_workgroup_size_x, Ordering::Less);
59-
$macro_name!(max_compute_workgroup_size_y, Ordering::Less);
60-
$macro_name!(max_compute_workgroup_size_z, Ordering::Less);
61-
$macro_name!(max_compute_workgroups_per_dimension, Ordering::Less);
62-
63-
$macro_name!(max_immediate_size, Ordering::Less);
64-
$macro_name!(max_non_sampler_bindings, Ordering::Less);
65-
66-
$macro_name!(max_task_mesh_workgroup_total_count, Ordering::Less);
67-
$macro_name!(max_task_mesh_workgroups_per_dimension, Ordering::Less);
68-
$macro_name!(max_task_invocations_per_workgroup, Ordering::Less);
69-
$macro_name!(max_task_invocations_per_dimension, Ordering::Less);
70-
$macro_name!(max_mesh_invocations_per_workgroup, Ordering::Less);
71-
$macro_name!(max_mesh_invocations_per_dimension, Ordering::Less);
72-
73-
$macro_name!(max_task_payload_size, Ordering::Less);
74-
$macro_name!(max_mesh_output_vertices, Ordering::Less);
75-
$macro_name!(max_mesh_output_primitives, Ordering::Less);
76-
$macro_name!(max_mesh_output_layers, Ordering::Less);
77-
$macro_name!(max_mesh_multiview_view_count, Ordering::Less);
78-
79-
$macro_name!(max_blas_primitive_count, Ordering::Less);
80-
$macro_name!(max_blas_geometry_count, Ordering::Less);
81-
$macro_name!(max_tlas_instance_count, Ordering::Less);
82-
83-
$macro_name!(max_multiview_view_count, Ordering::Less);
13+
macro_rules! WithLimits {
14+
(
15+
$(#[$StructMeta:meta])*
16+
$StructVis:vis
17+
struct $Struct:ident {
18+
$(
19+
$(#[doc = $literal:literal])*
20+
$(#[cfg_attr($Cond:meta, $Output:meta)])*
21+
#[custom(ordering($Ordering:ident))]
22+
$(#[$FieldMeta:meta])*
23+
$FieldVis:vis
24+
$Field:ident: $FieldType:ty
25+
),* $(,)?
26+
}
27+
) => {
28+
/// Invoke a macro for each of the limits.
29+
///
30+
/// The supplied macro should take two arguments. The first is a limit name, as
31+
/// an identifier, typically used to access a member of `struct Limits`. The
32+
/// second is `Ordering::Less` if valid values are less than the limit (the
33+
/// common case), or `Ordering::Greater` if valid values are more than the limit
34+
/// (for limits like alignments, which are minima instead of maxima).
35+
macro_rules! with_limits {
36+
($macro_name:ident) => {
37+
$(
38+
$macro_name!($Field, Ordering::$Ordering);
39+
)*
40+
};
41+
}
8442
};
8543
}
8644

@@ -120,112 +78,146 @@ macro_rules! with_limits {
12078
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
12179
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12280
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase", default))]
81+
#[macro_rules_derive(WithLimits)]
12382
pub struct Limits {
12483
/// Maximum allowed value for the `size.width` of a texture created with `TextureDimension::D1`.
12584
/// Defaults to 8192. Higher is "better".
12685
#[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension1D"))]
86+
#[custom(ordering(Less))]
12787
pub max_texture_dimension_1d: u32,
12888
/// Maximum allowed value for the `size.width` and `size.height` of a texture created with `TextureDimension::D2`.
12989
/// Defaults to 8192. Higher is "better".
13090
#[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension2D"))]
91+
#[custom(ordering(Less))]
13192
pub max_texture_dimension_2d: u32,
13293
/// Maximum allowed value for the `size.width`, `size.height`, and `size.depth_or_array_layers`
13394
/// of a texture created with `TextureDimension::D3`.
13495
/// Defaults to 2048. Higher is "better".
13596
#[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension3D"))]
97+
#[custom(ordering(Less))]
13698
pub max_texture_dimension_3d: u32,
13799
/// Maximum allowed value for the `size.depth_or_array_layers` of a texture created with `TextureDimension::D2`.
138100
/// Defaults to 256. Higher is "better".
101+
#[custom(ordering(Less))]
139102
pub max_texture_array_layers: u32,
140103
/// Amount of bind groups that can be attached to a pipeline at the same time. Defaults to 4. Higher is "better".
104+
#[custom(ordering(Less))]
141105
pub max_bind_groups: u32,
142106
/// Maximum binding index allowed in `create_bind_group_layout`. Defaults to 1000. Higher is "better".
107+
#[custom(ordering(Less))]
143108
pub max_bindings_per_bind_group: u32,
144109
/// Amount of uniform buffer bindings that can be dynamic in a single pipeline. Defaults to 8. Higher is "better".
110+
#[custom(ordering(Less))]
145111
pub max_dynamic_uniform_buffers_per_pipeline_layout: u32,
146112
/// Amount of storage buffer bindings that can be dynamic in a single pipeline. Defaults to 4. Higher is "better".
113+
#[custom(ordering(Less))]
147114
pub max_dynamic_storage_buffers_per_pipeline_layout: u32,
148115
/// Amount of sampled textures visible in a single shader stage. Defaults to 16. Higher is "better".
116+
#[custom(ordering(Less))]
149117
pub max_sampled_textures_per_shader_stage: u32,
150118
/// Amount of samplers visible in a single shader stage. Defaults to 16. Higher is "better".
119+
#[custom(ordering(Less))]
151120
pub max_samplers_per_shader_stage: u32,
152121
/// Amount of storage buffers visible in a single shader stage. Defaults to 8. Higher is "better".
122+
#[custom(ordering(Less))]
153123
pub max_storage_buffers_per_shader_stage: u32,
154124
/// Amount of storage textures visible in a single shader stage. Defaults to 4. Higher is "better".
125+
#[custom(ordering(Less))]
155126
pub max_storage_textures_per_shader_stage: u32,
156127
/// Amount of uniform buffers visible in a single shader stage. Defaults to 12. Higher is "better".
128+
#[custom(ordering(Less))]
157129
pub max_uniform_buffers_per_shader_stage: u32,
158130
/// Amount of individual resources within binding arrays that can be accessed in a single shader stage. Applies
159131
/// to all types of bindings except samplers.
160132
///
161133
/// This "defaults" to 0. However if binding arrays are supported, all devices can support 500,000. Higher is "better".
134+
#[custom(ordering(Less))]
162135
pub max_binding_array_elements_per_shader_stage: u32,
163136
/// Amount of individual acceleration structures within binding arrays that can be accessed in a single shader stage.
164137
///
165138
/// This "defaults" to 0. Higher is "better".
139+
#[custom(ordering(Less))]
166140
pub max_binding_array_acceleration_structure_elements_per_shader_stage: u32,
167141
/// Amount of individual samplers within binding arrays that can be accessed in a single shader stage.
168142
///
169143
/// This "defaults" to 0. However if binding arrays are supported, all devices can support 1,000. Higher is "better".
144+
#[custom(ordering(Less))]
170145
pub max_binding_array_sampler_elements_per_shader_stage: u32,
171146
/// Maximum size in bytes of a binding to a uniform buffer. Defaults to 64 KiB. Higher is "better".
147+
#[custom(ordering(Less))]
172148
pub max_uniform_buffer_binding_size: u64,
173149
/// Maximum size in bytes of a binding to a storage buffer. Defaults to 128 MiB. Higher is "better".
150+
#[custom(ordering(Less))]
174151
pub max_storage_buffer_binding_size: u64,
175152
/// Maximum length of `VertexState::buffers` when creating a `RenderPipeline`.
176153
/// Defaults to 8. Higher is "better".
154+
#[custom(ordering(Less))]
177155
pub max_vertex_buffers: u32,
178156
/// A limit above which buffer allocations are guaranteed to fail.
179157
/// Defaults to 256 MiB. Higher is "better".
180158
///
181159
/// Buffer allocations below the maximum buffer size may not succeed depending on available memory,
182160
/// fragmentation and other factors.
161+
#[custom(ordering(Less))]
183162
pub max_buffer_size: u64,
184163
/// Maximum length of `VertexBufferLayout::attributes`, summed over all `VertexState::buffers`,
185164
/// when creating a `RenderPipeline`.
186165
/// Defaults to 16. Higher is "better".
166+
#[custom(ordering(Less))]
187167
pub max_vertex_attributes: u32,
188168
/// Maximum value for `VertexBufferLayout::array_stride` when creating a `RenderPipeline`.
189169
/// Defaults to 2048. Higher is "better".
170+
#[custom(ordering(Less))]
190171
pub max_vertex_buffer_array_stride: u32,
191172
/// Maximum value for the number of input or output variables for inter-stage communication
192173
/// (like vertex outputs or fragment inputs) `@location(…)`s (in WGSL parlance)
193174
/// when creating a `RenderPipeline`.
194175
/// Defaults to 16. Higher is "better".
176+
#[custom(ordering(Less))]
195177
pub max_inter_stage_shader_variables: u32,
196178
/// Required `BufferBindingType::Uniform` alignment for `BufferBinding::offset`
197179
/// when creating a `BindGroup`, or for `set_bind_group` `dynamicOffsets`.
198180
/// Defaults to 256. Lower is "better".
181+
#[custom(ordering(Greater))]
199182
pub min_uniform_buffer_offset_alignment: u32,
200183
/// Required `BufferBindingType::Storage` alignment for `BufferBinding::offset`
201184
/// when creating a `BindGroup`, or for `set_bind_group` `dynamicOffsets`.
202185
/// Defaults to 256. Lower is "better".
186+
#[custom(ordering(Greater))]
203187
pub min_storage_buffer_offset_alignment: u32,
204188
/// The maximum allowed number of color attachments.
189+
#[custom(ordering(Less))]
205190
pub max_color_attachments: u32,
206191
/// The maximum number of bytes necessary to hold one sample (pixel or subpixel) of render
207192
/// pipeline output data, across all color attachments as described by [`TextureFormat::target_pixel_byte_cost`]
208193
/// and [`TextureFormat::target_component_alignment`]. Defaults to 32. Higher is "better".
209194
///
210195
/// ⚠️ `Rgba8Unorm`/`Rgba8Snorm`/`Bgra8Unorm`/`Bgra8Snorm` are deceptively 8 bytes per sample. ⚠️
196+
#[custom(ordering(Less))]
211197
pub max_color_attachment_bytes_per_sample: u32,
212198
/// Maximum number of bytes used for workgroup memory in a compute entry point. Defaults to
213199
/// 16384. Higher is "better".
200+
#[custom(ordering(Less))]
214201
pub max_compute_workgroup_storage_size: u32,
215202
/// Maximum value of the product of the `workgroup_size` dimensions for a compute entry-point.
216203
/// Defaults to 256. Higher is "better".
204+
#[custom(ordering(Less))]
217205
pub max_compute_invocations_per_workgroup: u32,
218206
/// The maximum value of the `workgroup_size` X dimension for a compute stage `ShaderModule` entry-point.
219207
/// Defaults to 256. Higher is "better".
208+
#[custom(ordering(Less))]
220209
pub max_compute_workgroup_size_x: u32,
221210
/// The maximum value of the `workgroup_size` Y dimension for a compute stage `ShaderModule` entry-point.
222211
/// Defaults to 256. Higher is "better".
212+
#[custom(ordering(Less))]
223213
pub max_compute_workgroup_size_y: u32,
224214
/// The maximum value of the `workgroup_size` Z dimension for a compute stage `ShaderModule` entry-point.
225215
/// Defaults to 64. Higher is "better".
216+
#[custom(ordering(Less))]
226217
pub max_compute_workgroup_size_z: u32,
227218
/// The maximum value for each dimension of a `ComputePass::dispatch(x, y, z)` operation.
228219
/// Defaults to 65535. Higher is "better".
220+
#[custom(ordering(Less))]
229221
pub max_compute_workgroups_per_dimension: u32,
230222

231223
/// Amount of storage available for immediates in bytes. Defaults to 0. Higher is "better".
@@ -237,6 +229,7 @@ pub struct Limits {
237229
/// - Metal: 4096 bytes
238230
/// - OpenGL doesn't natively support immediates, and are emulated with uniforms,
239231
/// so this number is less useful but likely 256.
232+
#[custom(ordering(Less))]
240233
pub max_immediate_size: u32,
241234
/// Maximum number of live non-sampler bindings.
242235
///
@@ -247,55 +240,72 @@ pub struct Limits {
247240
///
248241
/// This limit only affects the d3d12 backend. Using a large number will allow the device
249242
/// to create many bind groups at the cost of a large up-front allocation at device creation.
243+
#[custom(ordering(Less))]
250244
pub max_non_sampler_bindings: u32,
251245

252246
/// The maximum total value for a `RenderPass::draw_mesh_tasks(x, y, z)` operation or the
253247
/// `@builtin(mesh_task_size)` returned from a task shader. Higher is "better".
248+
#[custom(ordering(Less))]
254249
pub max_task_mesh_workgroup_total_count: u32,
255250
/// The maximum value for each dimension of a `RenderPass::draw_mesh_tasks(x, y, z)` operation.
256251
/// Also for task shader outputs. Higher is "better".
252+
#[custom(ordering(Less))]
257253
pub max_task_mesh_workgroups_per_dimension: u32,
258254
// These are fundamentally different. It is very common for limits on mesh shaders to be much lower.
259255
/// Maximum total number of invocations, or threads, per task shader workgroup. Higher is "better".
256+
#[custom(ordering(Less))]
260257
pub max_task_invocations_per_workgroup: u32,
261258
/// The maximum value for each dimension of a task shader's workgroup size. Higher is "better".
259+
#[custom(ordering(Less))]
262260
pub max_task_invocations_per_dimension: u32,
263261
/// Maximum total number of invocations, or threads, per mesh shader workgroup. Higher is "better".
262+
#[custom(ordering(Less))]
264263
pub max_mesh_invocations_per_workgroup: u32,
265264
/// The maximum value for each dimension of a mesh shader's workgroup size. Higher is "better".
265+
#[custom(ordering(Less))]
266266
pub max_mesh_invocations_per_dimension: u32,
267267

268268
/// The maximum size of the payload passed from task to mesh shader. Higher is "better".
269+
#[custom(ordering(Less))]
269270
pub max_task_payload_size: u32,
270271
/// The maximum number of vertices that a mesh shader may output. Higher is "better".
272+
#[custom(ordering(Less))]
271273
pub max_mesh_output_vertices: u32,
272274
/// The maximum number of primitives that a mesh shader may output. Higher is "better".
275+
#[custom(ordering(Less))]
273276
pub max_mesh_output_primitives: u32,
274277
/// The maximum number of layers that can be output from a mesh shader. Higher is "better".
275278
/// See [#8509](https://github.com/gfx-rs/wgpu/issues/8509).
279+
#[custom(ordering(Less))]
276280
pub max_mesh_output_layers: u32,
277281
/// The maximum number of views that can be used by a mesh shader in multiview rendering.
278282
/// Higher is "better".
283+
#[custom(ordering(Less))]
279284
pub max_mesh_multiview_view_count: u32,
280285

281286
/// The maximum number of primitive (ex: triangles, aabbs) a BLAS is allowed to have. Requesting
282287
/// more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_QUERY`]
283288
/// is enabled.
289+
#[custom(ordering(Less))]
284290
pub max_blas_primitive_count: u32,
285291
/// The maximum number of geometry descriptors a BLAS is allowed to have. Requesting
286292
/// more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_QUERY`]
287293
/// is enabled.
294+
#[custom(ordering(Less))]
288295
pub max_blas_geometry_count: u32,
289296
/// The maximum number of instances a TLAS is allowed to have. Requesting more than 0 during
290297
/// device creation only makes sense if [`Features::EXPERIMENTAL_RAY_QUERY`]
291298
/// is enabled.
299+
#[custom(ordering(Less))]
292300
pub max_tlas_instance_count: u32,
293301
/// The maximum number of acceleration structures allowed to be used in a shader stage.
294302
/// Requesting more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_QUERY`]
295303
/// is enabled.
304+
#[custom(ordering(Less))]
296305
pub max_acceleration_structures_per_shader_stage: u32,
297306

298307
/// The maximum number of views that can be used in multiview rendering
308+
#[custom(ordering(Less))]
299309
pub max_multiview_view_count: u32,
300310
}
301311

0 commit comments

Comments
 (0)