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;
20
21#[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
54impl<D: DomTypes> GPUSupportedLimitsMethods<D> for GPUSupportedLimits<D> {
56 fn MaxTextureDimension1D(&self) -> u32 {
58 self.limits.max_texture_dimension_1d
59 }
60
61 fn MaxTextureDimension2D(&self) -> u32 {
63 self.limits.max_texture_dimension_2d
64 }
65
66 fn MaxTextureDimension3D(&self) -> u32 {
68 self.limits.max_texture_dimension_3d
69 }
70
71 fn MaxTextureArrayLayers(&self) -> u32 {
73 self.limits.max_texture_array_layers
74 }
75
76 fn MaxBindGroups(&self) -> u32 {
78 self.limits.max_bind_groups
79 }
80
81 fn MaxBindGroupsPlusVertexBuffers(&self) -> u32 {
83 self.limits.max_bind_groups_plus_vertex_buffers
84 }
85
86 fn MaxBindingsPerBindGroup(&self) -> u32 {
95 self.limits.max_bindings_per_bind_group
96 }
97
98 fn MaxDynamicUniformBuffersPerPipelineLayout(&self) -> u32 {
100 self.limits.max_dynamic_uniform_buffers_per_pipeline_layout
101 }
102
103 fn MaxDynamicStorageBuffersPerPipelineLayout(&self) -> u32 {
105 self.limits.max_dynamic_storage_buffers_per_pipeline_layout
106 }
107
108 fn MaxSampledTexturesPerShaderStage(&self) -> u32 {
110 self.limits.max_sampled_textures_per_shader_stage
111 }
112
113 fn MaxSamplersPerShaderStage(&self) -> u32 {
115 self.limits.max_samplers_per_shader_stage
116 }
117
118 fn MaxStorageBuffersPerShaderStage(&self) -> u32 {
120 self.limits.max_storage_buffers_per_shader_stage
121 }
122
123 fn MaxStorageBuffersInVertexStage(&self) -> u32 {
125 self.limits.max_storage_buffers_per_shader_stage
127 }
128
129 fn MaxStorageBuffersInFragmentStage(&self) -> u32 {
131 self.limits.max_storage_buffers_per_shader_stage
133 }
134
135 fn MaxStorageTexturesPerShaderStage(&self) -> u32 {
137 self.limits.max_storage_textures_per_shader_stage
138 }
139
140 fn MaxStorageTexturesInVertexStage(&self) -> u32 {
142 self.limits.max_storage_textures_per_shader_stage
144 }
145
146 fn MaxStorageTexturesInFragmentStage(&self) -> u32 {
148 self.limits.max_storage_textures_per_shader_stage
150 }
151
152 fn MaxUniformBuffersPerShaderStage(&self) -> u32 {
154 self.limits.max_uniform_buffers_per_shader_stage
155 }
156
157 fn MaxUniformBufferBindingSize(&self) -> u64 {
159 self.limits.max_uniform_buffer_binding_size
160 }
161
162 fn MaxStorageBufferBindingSize(&self) -> u64 {
164 self.limits.max_storage_buffer_binding_size
165 }
166
167 fn MinUniformBufferOffsetAlignment(&self) -> u32 {
169 self.limits.min_uniform_buffer_offset_alignment
170 }
171
172 fn MinStorageBufferOffsetAlignment(&self) -> u32 {
174 self.limits.min_storage_buffer_offset_alignment
175 }
176
177 fn MaxVertexBuffers(&self) -> u32 {
179 self.limits.max_vertex_buffers
180 }
181
182 fn MaxBufferSize(&self) -> u64 {
184 self.limits.max_buffer_size
185 }
186
187 fn MaxVertexAttributes(&self) -> u32 {
189 self.limits.max_vertex_attributes
190 }
191
192 fn MaxVertexBufferArrayStride(&self) -> u32 {
194 self.limits.max_vertex_buffer_array_stride
195 }
196
197 fn MaxInterStageShaderVariables(&self) -> u32 {
199 self.limits.max_inter_stage_shader_variables
200 }
201
202 fn MaxColorAttachments(&self) -> u32 {
204 self.limits.max_color_attachments
205 }
206
207 fn MaxColorAttachmentBytesPerSample(&self) -> u32 {
209 self.limits.max_color_attachment_bytes_per_sample
210 }
211
212 fn MaxComputeWorkgroupStorageSize(&self) -> u32 {
214 self.limits.max_compute_workgroup_storage_size
215 }
216
217 fn MaxComputeInvocationsPerWorkgroup(&self) -> u32 {
219 self.limits.max_compute_invocations_per_workgroup
220 }
221
222 fn MaxComputeWorkgroupSizeX(&self) -> u32 {
224 self.limits.max_compute_workgroup_size_x
225 }
226
227 fn MaxComputeWorkgroupSizeY(&self) -> u32 {
229 self.limits.max_compute_workgroup_size_y
230 }
231
232 fn MaxComputeWorkgroupSizeZ(&self) -> u32 {
234 self.limits.max_compute_workgroup_size_z
235 }
236
237 fn MaxComputeWorkgroupsPerDimension(&self) -> u32 {
239 self.limits.max_compute_workgroups_per_dimension
240 }
241}
242
243pub(crate) fn set_limit(limits: &mut Limits, limit: &str, value: u64) -> bool {
245 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 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 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 let mut v: u32 = 0;
312 set_maximum(&mut v, value)
313 },
314 "maxStorageBuffersInFragmentStage" => {
315 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 let mut v: u32 = 0;
329 set_maximum(&mut v, value)
330 },
331 "maxStorageTexturesInFragmentStage" => {
332 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}