Skip to main content

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