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