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