1use 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;
20use crate::traits::Equivalence;
21
22#[dom_struct]
24pub struct GPUSupportedLimits<D: DomTypes> {
25 reflector_: Reflector,
26 #[ignore_malloc_size_of = "defined in wgpu-types"]
27 #[no_trace]
28 limits: Limits,
29 #[no_trace = "PhantomData does not exist"]
30 phantom: PhantomData<D>,
31}
32
33impl<D: Equivalence> GPUSupportedLimits<D> {
34 fn new_inherited(limits: Limits) -> Self {
35 Self {
36 reflector_: Reflector::new(),
37 limits,
38 phantom: PhantomData,
39 }
40 }
41
42 pub fn new(cx: &mut JSContext, global: &D::GlobalScope, limits: Limits) -> DomRoot<Self> {
43 reflect_dom_object_with_wrap::<D, _, _>(
44 Box::new(Self::new_inherited(limits)),
45 global,
46 cx,
47 GPUSupportedLimitsWrap::<D>,
48 )
49 }
50}
51
52impl<D: DomTypes> GPUSupportedLimitsMethods<D> for GPUSupportedLimits<D> {
54 fn MaxTextureDimension1D(&self) -> u32 {
56 self.limits.max_texture_dimension_1d
57 }
58
59 fn MaxTextureDimension2D(&self) -> u32 {
61 self.limits.max_texture_dimension_2d
62 }
63
64 fn MaxTextureDimension3D(&self) -> u32 {
66 self.limits.max_texture_dimension_3d
67 }
68
69 fn MaxTextureArrayLayers(&self) -> u32 {
71 self.limits.max_texture_array_layers
72 }
73
74 fn MaxBindGroups(&self) -> u32 {
76 self.limits.max_bind_groups
77 }
78
79 fn MaxBindGroupsPlusVertexBuffers(&self) -> u32 {
81 self.limits.max_bind_groups_plus_vertex_buffers
82 }
83
84 fn MaxBindingsPerBindGroup(&self) -> u32 {
93 self.limits.max_bindings_per_bind_group
94 }
95
96 fn MaxDynamicUniformBuffersPerPipelineLayout(&self) -> u32 {
98 self.limits.max_dynamic_uniform_buffers_per_pipeline_layout
99 }
100
101 fn MaxDynamicStorageBuffersPerPipelineLayout(&self) -> u32 {
103 self.limits.max_dynamic_storage_buffers_per_pipeline_layout
104 }
105
106 fn MaxSampledTexturesPerShaderStage(&self) -> u32 {
108 self.limits.max_sampled_textures_per_shader_stage
109 }
110
111 fn MaxSamplersPerShaderStage(&self) -> u32 {
113 self.limits.max_samplers_per_shader_stage
114 }
115
116 fn MaxStorageBuffersPerShaderStage(&self) -> u32 {
118 self.limits.max_storage_buffers_per_shader_stage
119 }
120
121 fn MaxStorageBuffersInVertexStage(&self) -> u32 {
123 self.limits.max_storage_buffers_per_shader_stage
125 }
126
127 fn MaxStorageBuffersInFragmentStage(&self) -> u32 {
129 self.limits.max_storage_buffers_per_shader_stage
131 }
132
133 fn MaxStorageTexturesPerShaderStage(&self) -> u32 {
135 self.limits.max_storage_textures_per_shader_stage
136 }
137
138 fn MaxStorageTexturesInVertexStage(&self) -> u32 {
140 self.limits.max_storage_textures_per_shader_stage
142 }
143
144 fn MaxStorageTexturesInFragmentStage(&self) -> u32 {
146 self.limits.max_storage_textures_per_shader_stage
148 }
149
150 fn MaxUniformBuffersPerShaderStage(&self) -> u32 {
152 self.limits.max_uniform_buffers_per_shader_stage
153 }
154
155 fn MaxUniformBufferBindingSize(&self) -> u64 {
157 self.limits.max_uniform_buffer_binding_size
158 }
159
160 fn MaxStorageBufferBindingSize(&self) -> u64 {
162 self.limits.max_storage_buffer_binding_size
163 }
164
165 fn MinUniformBufferOffsetAlignment(&self) -> u32 {
167 self.limits.min_uniform_buffer_offset_alignment
168 }
169
170 fn MinStorageBufferOffsetAlignment(&self) -> u32 {
172 self.limits.min_storage_buffer_offset_alignment
173 }
174
175 fn MaxVertexBuffers(&self) -> u32 {
177 self.limits.max_vertex_buffers
178 }
179
180 fn MaxBufferSize(&self) -> u64 {
182 self.limits.max_buffer_size
183 }
184
185 fn MaxVertexAttributes(&self) -> u32 {
187 self.limits.max_vertex_attributes
188 }
189
190 fn MaxVertexBufferArrayStride(&self) -> u32 {
192 self.limits.max_vertex_buffer_array_stride
193 }
194
195 fn MaxInterStageShaderVariables(&self) -> u32 {
197 self.limits.max_inter_stage_shader_variables
198 }
199
200 fn MaxColorAttachments(&self) -> u32 {
202 self.limits.max_color_attachments
203 }
204
205 fn MaxColorAttachmentBytesPerSample(&self) -> u32 {
207 self.limits.max_color_attachment_bytes_per_sample
208 }
209
210 fn MaxComputeWorkgroupStorageSize(&self) -> u32 {
212 self.limits.max_compute_workgroup_storage_size
213 }
214
215 fn MaxComputeInvocationsPerWorkgroup(&self) -> u32 {
217 self.limits.max_compute_invocations_per_workgroup
218 }
219
220 fn MaxComputeWorkgroupSizeX(&self) -> u32 {
222 self.limits.max_compute_workgroup_size_x
223 }
224
225 fn MaxComputeWorkgroupSizeY(&self) -> u32 {
227 self.limits.max_compute_workgroup_size_y
228 }
229
230 fn MaxComputeWorkgroupSizeZ(&self) -> u32 {
232 self.limits.max_compute_workgroup_size_z
233 }
234
235 fn MaxComputeWorkgroupsPerDimension(&self) -> u32 {
237 self.limits.max_compute_workgroups_per_dimension
238 }
239}
240
241pub(crate) fn set_limit(limits: &mut Limits, limit: &str, value: u64) -> bool {
243 fn set_maximum<T>(limit: &mut T, value: u64) -> bool
247 where
248 T: Ord + Copy + TryFrom<u64> + UpperBounded,
249 {
250 if let Ok(value) = T::try_from(value) {
251 *limit = value.max(*limit);
252 true
253 } else {
254 false
255 }
256 }
257
258 fn set_alignment<T>(limit: &mut T, value: u64) -> bool
262 where
263 T: Ord + Copy + TryFrom<u64> + UpperBounded,
264 {
265 if !value.is_power_of_two() {
266 return false;
267 }
268 if let Ok(value) = T::try_from(value) {
269 *limit = value.min(*limit);
270 true
271 } else {
272 false
273 }
274 }
275
276 match limit {
278 "maxTextureDimension1D" => set_maximum(&mut limits.max_texture_dimension_1d, value),
279 "maxTextureDimension2D" => set_maximum(&mut limits.max_texture_dimension_2d, value),
280 "maxTextureDimension3D" => set_maximum(&mut limits.max_texture_dimension_3d, value),
281 "maxTextureArrayLayers" => set_maximum(&mut limits.max_texture_array_layers, value),
282 "maxBindGroups" => set_maximum(&mut limits.max_bind_groups, value),
283 "maxBindGroupsPlusVertexBuffers" => {
284 set_maximum(&mut limits.max_bind_groups_plus_vertex_buffers, value)
285 },
286 "maxImmediateSize" => set_maximum(&mut limits.max_immediate_size, value),
287 "maxBindingsPerBindGroup" => set_maximum(&mut limits.max_bindings_per_bind_group, value),
288 "maxDynamicUniformBuffersPerPipelineLayout" => set_maximum(
289 &mut limits.max_dynamic_uniform_buffers_per_pipeline_layout,
290 value,
291 ),
292 "maxDynamicStorageBuffersPerPipelineLayout" => set_maximum(
293 &mut limits.max_dynamic_storage_buffers_per_pipeline_layout,
294 value,
295 ),
296 "maxSampledTexturesPerShaderStage" => {
297 set_maximum(&mut limits.max_sampled_textures_per_shader_stage, value)
298 },
299 "maxSamplersPerShaderStage" => {
300 set_maximum(&mut limits.max_samplers_per_shader_stage, value)
301 },
302 "maxStorageBuffersPerShaderStage" => {
303 set_maximum(&mut limits.max_storage_buffers_per_shader_stage, value)
304 },
305 "maxStorageBuffersInVertexStage" => {
306 let mut v: u32 = 0;
310 set_maximum(&mut v, value)
311 },
312 "maxStorageBuffersInFragmentStage" => {
313 let mut v: u32 = 0;
317 set_maximum(&mut v, value)
318 },
319 "maxStorageTexturesPerShaderStage" => {
320 set_maximum(&mut limits.max_storage_textures_per_shader_stage, value)
321 },
322 "maxStorageTexturesInVertexStage" => {
323 let mut v: u32 = 0;
327 set_maximum(&mut v, value)
328 },
329 "maxStorageTexturesInFragmentStage" => {
330 let mut v: u32 = 0;
334 set_maximum(&mut v, value)
335 },
336 "maxUniformBuffersPerShaderStage" => {
337 set_maximum(&mut limits.max_uniform_buffers_per_shader_stage, value)
338 },
339 "maxUniformBufferBindingSize" => {
340 set_maximum(&mut limits.max_uniform_buffer_binding_size, value)
341 },
342 "maxStorageBufferBindingSize" => {
343 set_maximum(&mut limits.max_storage_buffer_binding_size, value)
344 },
345 "minUniformBufferOffsetAlignment" => {
346 set_alignment(&mut limits.min_uniform_buffer_offset_alignment, value)
347 },
348 "minStorageBufferOffsetAlignment" => {
349 set_alignment(&mut limits.min_storage_buffer_offset_alignment, value)
350 },
351 "maxVertexBuffers" => set_maximum(&mut limits.max_vertex_buffers, value),
352 "maxBufferSize" => set_maximum(&mut limits.max_buffer_size, value),
353 "maxVertexAttributes" => set_maximum(&mut limits.max_vertex_attributes, value),
354 "maxVertexBufferArrayStride" => {
355 set_maximum(&mut limits.max_vertex_buffer_array_stride, value)
356 },
357 "maxInterStageShaderVariables" => {
358 set_maximum(&mut limits.max_inter_stage_shader_variables, value)
359 },
360 "maxColorAttachments" => set_maximum(&mut limits.max_color_attachments, value),
361 "maxColorAttachmentBytesPerSample" => {
362 set_maximum(&mut limits.max_color_attachment_bytes_per_sample, value)
363 },
364 "maxComputeWorkgroupStorageSize" => {
365 set_maximum(&mut limits.max_compute_workgroup_storage_size, value)
366 },
367 "maxComputeInvocationsPerWorkgroup" => {
368 set_maximum(&mut limits.max_compute_invocations_per_workgroup, value)
369 },
370 "maxComputeWorkgroupSizeX" => set_maximum(&mut limits.max_compute_workgroup_size_x, value),
371 "maxComputeWorkgroupSizeY" => set_maximum(&mut limits.max_compute_workgroup_size_y, value),
372 "maxComputeWorkgroupSizeZ" => set_maximum(&mut limits.max_compute_workgroup_size_z, value),
373 "maxComputeWorkgroupsPerDimension" => {
374 set_maximum(&mut limits.max_compute_workgroups_per_dimension, value)
375 },
376 _ => false,
377 }
378}