script/dom/webgpu/
gpusupportedlimits.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use GPUSupportedLimits_Binding::GPUSupportedLimitsMethods;
6use dom_struct::dom_struct;
7use num_traits::bounds::UpperBounded;
8use wgpu_types::Limits;
9
10use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUSupportedLimits_Binding;
11use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
12use crate::dom::bindings::root::DomRoot;
13use crate::dom::globalscope::GlobalScope;
14use crate::script_runtime::CanGc;
15
16#[dom_struct]
17pub(crate) struct GPUSupportedLimits {
18    reflector_: Reflector,
19    #[ignore_malloc_size_of = "defined in wgpu-types"]
20    #[no_trace]
21    limits: Limits,
22}
23
24impl GPUSupportedLimits {
25    fn new_inherited(limits: Limits) -> Self {
26        Self {
27            reflector_: Reflector::new(),
28            limits,
29        }
30    }
31
32    pub(crate) fn new(global: &GlobalScope, limits: Limits, can_gc: CanGc) -> DomRoot<Self> {
33        reflect_dom_object(Box::new(Self::new_inherited(limits)), global, can_gc)
34    }
35}
36
37impl GPUSupportedLimitsMethods<crate::DomTypeHolder> for GPUSupportedLimits {
38    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxtexturedimension1d>
39    fn MaxTextureDimension1D(&self) -> u32 {
40        self.limits.max_texture_dimension_1d
41    }
42
43    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxtexturedimension2d>
44    fn MaxTextureDimension2D(&self) -> u32 {
45        self.limits.max_texture_dimension_2d
46    }
47
48    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxtexturedimension3d>
49    fn MaxTextureDimension3D(&self) -> u32 {
50        self.limits.max_texture_dimension_3d
51    }
52
53    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxtexturearraylayers>
54    fn MaxTextureArrayLayers(&self) -> u32 {
55        self.limits.max_texture_array_layers
56    }
57
58    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxbindgroups>
59    fn MaxBindGroups(&self) -> u32 {
60        self.limits.max_bind_groups
61    }
62
63    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxbindingsperbindgroup>
64    fn MaxBindingsPerBindGroup(&self) -> u32 {
65        self.limits.max_bindings_per_bind_group
66    }
67
68    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxdynamicuniformbuffersperpipelinelayout>
69    fn MaxDynamicUniformBuffersPerPipelineLayout(&self) -> u32 {
70        self.limits.max_dynamic_uniform_buffers_per_pipeline_layout
71    }
72
73    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxdynamicstoragebuffersperpipelinelayout>
74    fn MaxDynamicStorageBuffersPerPipelineLayout(&self) -> u32 {
75        self.limits.max_dynamic_storage_buffers_per_pipeline_layout
76    }
77
78    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxsampledtexturespershaderstage>
79    fn MaxSampledTexturesPerShaderStage(&self) -> u32 {
80        self.limits.max_sampled_textures_per_shader_stage
81    }
82
83    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxsamplerspershaderstage>
84    fn MaxSamplersPerShaderStage(&self) -> u32 {
85        self.limits.max_samplers_per_shader_stage
86    }
87
88    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxstoragebufferspershaderstage>
89    fn MaxStorageBuffersPerShaderStage(&self) -> u32 {
90        self.limits.max_storage_buffers_per_shader_stage
91    }
92
93    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxstoragetexturespershaderstage>
94    fn MaxStorageTexturesPerShaderStage(&self) -> u32 {
95        self.limits.max_storage_textures_per_shader_stage
96    }
97
98    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxuniformbufferspershaderstage>
99    fn MaxUniformBuffersPerShaderStage(&self) -> u32 {
100        self.limits.max_uniform_buffers_per_shader_stage
101    }
102
103    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxuniformbufferbindingsize>
104    fn MaxUniformBufferBindingSize(&self) -> u64 {
105        self.limits.max_uniform_buffer_binding_size as u64
106    }
107
108    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxstoragebufferbindingsize>
109    fn MaxStorageBufferBindingSize(&self) -> u64 {
110        self.limits.max_storage_buffer_binding_size as u64
111    }
112
113    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-minuniformbufferoffsetalignment>
114    fn MinUniformBufferOffsetAlignment(&self) -> u32 {
115        self.limits.min_uniform_buffer_offset_alignment
116    }
117
118    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-minstoragebufferoffsetalignment>
119    fn MinStorageBufferOffsetAlignment(&self) -> u32 {
120        self.limits.min_storage_buffer_offset_alignment
121    }
122
123    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxvertexbuffers>
124    fn MaxVertexBuffers(&self) -> u32 {
125        self.limits.max_vertex_buffers
126    }
127
128    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxbuffersize>
129    fn MaxBufferSize(&self) -> u64 {
130        self.limits.max_buffer_size
131    }
132
133    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxvertexattributes>
134    fn MaxVertexAttributes(&self) -> u32 {
135        self.limits.max_vertex_attributes
136    }
137
138    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxvertexbufferarraystride>
139    fn MaxVertexBufferArrayStride(&self) -> u32 {
140        self.limits.max_vertex_buffer_array_stride
141    }
142
143    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxinterstageshadercomponents>
144    fn MaxInterStageShaderComponents(&self) -> u32 {
145        self.limits.max_inter_stage_shader_components
146    }
147
148    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupstoragesize>
149    fn MaxComputeWorkgroupStorageSize(&self) -> u32 {
150        self.limits.max_compute_workgroup_storage_size
151    }
152
153    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeinvocationsperworkgroup>
154    fn MaxComputeInvocationsPerWorkgroup(&self) -> u32 {
155        self.limits.max_compute_invocations_per_workgroup
156    }
157
158    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupsizex>
159    fn MaxComputeWorkgroupSizeX(&self) -> u32 {
160        self.limits.max_compute_workgroup_size_x
161    }
162
163    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupsizey>
164    fn MaxComputeWorkgroupSizeY(&self) -> u32 {
165        self.limits.max_compute_workgroup_size_y
166    }
167
168    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupsizez>
169    fn MaxComputeWorkgroupSizeZ(&self) -> u32 {
170        self.limits.max_compute_workgroup_size_z
171    }
172
173    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcomputeworkgroupsperdimension>
174    fn MaxComputeWorkgroupsPerDimension(&self) -> u32 {
175        self.limits.max_compute_workgroups_per_dimension
176    }
177
178    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxbindgroupsplusvertexbuffers>
179    fn MaxBindGroupsPlusVertexBuffers(&self) -> u32 {
180        // Not on wgpu yet, so we craft it manually
181        self.limits.max_bind_groups + self.limits.max_vertex_buffers
182    }
183
184    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxinterstageshadervariables>
185    fn MaxInterStageShaderVariables(&self) -> u32 {
186        // Not in wgpu yet, so we use default value from spec
187        16
188    }
189
190    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcolorattachments>
191    fn MaxColorAttachments(&self) -> u32 {
192        self.limits.max_color_attachments
193    }
194
195    /// <https://gpuweb.github.io/gpuweb/#dom-gpusupportedlimits-maxcolorattachmentbytespersample>
196    fn MaxColorAttachmentBytesPerSample(&self) -> u32 {
197        self.limits.max_color_attachment_bytes_per_sample
198    }
199}
200
201/// Returns false if unknown limit or other value error
202pub(crate) fn set_limit(limits: &mut Limits, limit: &str, value: u64) -> bool {
203    /// per spec defaults are lower bounds for values
204    ///
205    /// <https://www.w3.org/TR/webgpu/#limit-class-maximum>
206    fn set_maximum<T>(limit: &mut T, value: u64) -> bool
207    where
208        T: Ord + Copy + TryFrom<u64> + UpperBounded,
209    {
210        if let Ok(value) = T::try_from(value) {
211            *limit = value.max(*limit);
212            true
213        } else {
214            false
215        }
216    }
217
218    /// per spec defaults are higher bounds for values
219    ///
220    /// <https://www.w3.org/TR/webgpu/#limit-class-alignment>
221    fn set_alignment<T>(limit: &mut T, value: u64) -> bool
222    where
223        T: Ord + Copy + TryFrom<u64> + UpperBounded,
224    {
225        if !value.is_power_of_two() {
226            return false;
227        }
228        if let Ok(value) = T::try_from(value) {
229            *limit = value.min(*limit);
230            true
231        } else {
232            false
233        }
234    }
235
236    match limit {
237        "maxTextureDimension1D" => set_maximum(&mut limits.max_texture_dimension_1d, value),
238        "maxTextureDimension2D" => set_maximum(&mut limits.max_texture_dimension_2d, value),
239        "maxTextureDimension3D" => set_maximum(&mut limits.max_texture_dimension_3d, value),
240        "maxTextureArrayLayers" => set_maximum(&mut limits.max_texture_array_layers, value),
241        "maxBindGroups" => set_maximum(&mut limits.max_bind_groups, value),
242        "maxBindGroupsPlusVertexBuffers" => {
243            // not in wgpu but we're allowed to give back better limits than requested.
244            // we use dummy value to still produce value verification
245            let mut v: u32 = 0;
246            set_maximum(&mut v, value)
247        },
248        "maxBindingsPerBindGroup" => set_maximum(&mut limits.max_bindings_per_bind_group, value),
249        "maxDynamicUniformBuffersPerPipelineLayout" => set_maximum(
250            &mut limits.max_dynamic_uniform_buffers_per_pipeline_layout,
251            value,
252        ),
253        "maxDynamicStorageBuffersPerPipelineLayout" => set_maximum(
254            &mut limits.max_dynamic_storage_buffers_per_pipeline_layout,
255            value,
256        ),
257        "maxSampledTexturesPerShaderStage" => {
258            set_maximum(&mut limits.max_sampled_textures_per_shader_stage, value)
259        },
260        "maxSamplersPerShaderStage" => {
261            set_maximum(&mut limits.max_samplers_per_shader_stage, value)
262        },
263        "maxStorageBuffersPerShaderStage" => {
264            set_maximum(&mut limits.max_storage_buffers_per_shader_stage, value)
265        },
266        "maxStorageTexturesPerShaderStage" => {
267            set_maximum(&mut limits.max_storage_textures_per_shader_stage, value)
268        },
269        "maxUniformBuffersPerShaderStage" => {
270            set_maximum(&mut limits.max_uniform_buffers_per_shader_stage, value)
271        },
272        "maxUniformBufferBindingSize" => {
273            set_maximum(&mut limits.max_uniform_buffer_binding_size, value)
274        },
275        "maxStorageBufferBindingSize" => {
276            set_maximum(&mut limits.max_storage_buffer_binding_size, value)
277        },
278        "minUniformBufferOffsetAlignment" => {
279            set_alignment(&mut limits.min_uniform_buffer_offset_alignment, value)
280        },
281        "minStorageBufferOffsetAlignment" => {
282            set_alignment(&mut limits.min_storage_buffer_offset_alignment, value)
283        },
284        "maxVertexBuffers" => set_maximum(&mut limits.max_vertex_buffers, value),
285        "maxBufferSize" => set_maximum(&mut limits.max_buffer_size, value),
286        "maxVertexAttributes" => set_maximum(&mut limits.max_vertex_attributes, value),
287        "maxVertexBufferArrayStride" => {
288            set_maximum(&mut limits.max_vertex_buffer_array_stride, value)
289        },
290        "maxInterStageShaderComponents" => {
291            set_maximum(&mut limits.max_inter_stage_shader_components, value)
292        },
293        "maxInterStageShaderVariables" => {
294            // not in wgpu but we're allowed to give back better limits than requested.
295            // we use dummy value to still produce value verification
296            let mut v: u32 = 0;
297            set_maximum(&mut v, value)
298        },
299        "maxColorAttachments" => set_maximum(&mut limits.max_color_attachments, value),
300        "maxColorAttachmentBytesPerSample" => {
301            set_maximum(&mut limits.max_color_attachment_bytes_per_sample, value)
302        },
303        "maxComputeWorkgroupStorageSize" => {
304            set_maximum(&mut limits.max_compute_workgroup_storage_size, value)
305        },
306        "maxComputeInvocationsPerWorkgroup" => {
307            set_maximum(&mut limits.max_compute_invocations_per_workgroup, value)
308        },
309        "maxComputeWorkgroupSizeX" => set_maximum(&mut limits.max_compute_workgroup_size_x, value),
310        "maxComputeWorkgroupSizeY" => set_maximum(&mut limits.max_compute_workgroup_size_y, value),
311        "maxComputeWorkgroupSizeZ" => set_maximum(&mut limits.max_compute_workgroup_size_z, value),
312        "maxComputeWorkgroupsPerDimension" => {
313            set_maximum(&mut limits.max_compute_workgroups_per_dimension, value)
314        },
315        _ => false,
316    }
317}