Skip to main content

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