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 webgpu_traits::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(crate) fn new(
43 cx: &mut JSContext,
44 global: &D::GlobalScope,
45 limits: Limits,
46 ) -> DomRoot<Self> {
47 reflect_dom_object_with_wrap::<D, _, _>(
48 Box::new(Self::new_inherited(limits)),
49 global,
50 cx,
51 GPUSupportedLimitsWrap::<D>,
52 )
53 }
54}
55
56impl<D: DomTypes> GPUSupportedLimitsMethods<D> for GPUSupportedLimits<D> {
58 fn MaxTextureDimension1D(&self) -> u32 {
60 self.limits.max_texture_dimension_1d
61 }
62
63 fn MaxTextureDimension2D(&self) -> u32 {
65 self.limits.max_texture_dimension_2d
66 }
67
68 fn MaxTextureDimension3D(&self) -> u32 {
70 self.limits.max_texture_dimension_3d
71 }
72
73 fn MaxTextureArrayLayers(&self) -> u32 {
75 self.limits.max_texture_array_layers
76 }
77
78 fn MaxBindGroups(&self) -> u32 {
80 self.limits.max_bind_groups
81 }
82
83 fn MaxBindGroupsPlusVertexBuffers(&self) -> u32 {
85 self.limits.max_bind_groups_plus_vertex_buffers
86 }
87
88 fn MaxBindingsPerBindGroup(&self) -> u32 {
97 self.limits.max_bindings_per_bind_group
98 }
99
100 fn MaxDynamicUniformBuffersPerPipelineLayout(&self) -> u32 {
102 self.limits.max_dynamic_uniform_buffers_per_pipeline_layout
103 }
104
105 fn MaxDynamicStorageBuffersPerPipelineLayout(&self) -> u32 {
107 self.limits.max_dynamic_storage_buffers_per_pipeline_layout
108 }
109
110 fn MaxSampledTexturesPerShaderStage(&self) -> u32 {
112 self.limits.max_sampled_textures_per_shader_stage
113 }
114
115 fn MaxSamplersPerShaderStage(&self) -> u32 {
117 self.limits.max_samplers_per_shader_stage
118 }
119
120 fn MaxStorageBuffersPerShaderStage(&self) -> u32 {
122 self.limits.max_storage_buffers_per_shader_stage
123 }
124
125 fn MaxStorageBuffersInVertexStage(&self) -> u32 {
127 self.limits.max_storage_buffers_per_shader_stage
129 }
130
131 fn MaxStorageBuffersInFragmentStage(&self) -> u32 {
133 self.limits.max_storage_buffers_per_shader_stage
135 }
136
137 fn MaxStorageTexturesPerShaderStage(&self) -> u32 {
139 self.limits.max_storage_textures_per_shader_stage
140 }
141
142 fn MaxStorageTexturesInVertexStage(&self) -> u32 {
144 self.limits.max_storage_textures_per_shader_stage
146 }
147
148 fn MaxStorageTexturesInFragmentStage(&self) -> u32 {
150 self.limits.max_storage_textures_per_shader_stage
152 }
153
154 fn MaxUniformBuffersPerShaderStage(&self) -> u32 {
156 self.limits.max_uniform_buffers_per_shader_stage
157 }
158
159 fn MaxUniformBufferBindingSize(&self) -> u64 {
161 self.limits.max_uniform_buffer_binding_size
162 }
163
164 fn MaxStorageBufferBindingSize(&self) -> u64 {
166 self.limits.max_storage_buffer_binding_size
167 }
168
169 fn MinUniformBufferOffsetAlignment(&self) -> u32 {
171 self.limits.min_uniform_buffer_offset_alignment
172 }
173
174 fn MinStorageBufferOffsetAlignment(&self) -> u32 {
176 self.limits.min_storage_buffer_offset_alignment
177 }
178
179 fn MaxVertexBuffers(&self) -> u32 {
181 self.limits.max_vertex_buffers
182 }
183
184 fn MaxBufferSize(&self) -> u64 {
186 self.limits.max_buffer_size
187 }
188
189 fn MaxVertexAttributes(&self) -> u32 {
191 self.limits.max_vertex_attributes
192 }
193
194 fn MaxVertexBufferArrayStride(&self) -> u32 {
196 self.limits.max_vertex_buffer_array_stride
197 }
198
199 fn MaxInterStageShaderVariables(&self) -> u32 {
201 self.limits.max_inter_stage_shader_variables
202 }
203
204 fn MaxColorAttachments(&self) -> u32 {
206 self.limits.max_color_attachments
207 }
208
209 fn MaxColorAttachmentBytesPerSample(&self) -> u32 {
211 self.limits.max_color_attachment_bytes_per_sample
212 }
213
214 fn MaxComputeWorkgroupStorageSize(&self) -> u32 {
216 self.limits.max_compute_workgroup_storage_size
217 }
218
219 fn MaxComputeInvocationsPerWorkgroup(&self) -> u32 {
221 self.limits.max_compute_invocations_per_workgroup
222 }
223
224 fn MaxComputeWorkgroupSizeX(&self) -> u32 {
226 self.limits.max_compute_workgroup_size_x
227 }
228
229 fn MaxComputeWorkgroupSizeY(&self) -> u32 {
231 self.limits.max_compute_workgroup_size_y
232 }
233
234 fn MaxComputeWorkgroupSizeZ(&self) -> u32 {
236 self.limits.max_compute_workgroup_size_z
237 }
238
239 fn MaxComputeWorkgroupsPerDimension(&self) -> u32 {
241 self.limits.max_compute_workgroups_per_dimension
242 }
243}
244
245pub(crate) fn set_limit(limits: &mut Limits, limit: &str, value: u64) -> bool {
247 fn set_maximum<T>(limit: &mut T, value: u64) -> bool
251 where
252 T: Ord + Copy + TryFrom<u64> + UpperBounded,
253 {
254 if let Ok(value) = T::try_from(value) {
255 *limit = value.max(*limit);
256 true
257 } else {
258 false
259 }
260 }
261
262 fn set_alignment<T>(limit: &mut T, value: u64) -> bool
266 where
267 T: Ord + Copy + TryFrom<u64> + UpperBounded,
268 {
269 if !value.is_power_of_two() {
270 return false;
271 }
272 if let Ok(value) = T::try_from(value) {
273 *limit = value.min(*limit);
274 true
275 } else {
276 false
277 }
278 }
279
280 match limit {
282 "maxTextureDimension1D" => set_maximum(&mut limits.max_texture_dimension_1d, value),
283 "maxTextureDimension2D" => set_maximum(&mut limits.max_texture_dimension_2d, value),
284 "maxTextureDimension3D" => set_maximum(&mut limits.max_texture_dimension_3d, value),
285 "maxTextureArrayLayers" => set_maximum(&mut limits.max_texture_array_layers, value),
286 "maxBindGroups" => set_maximum(&mut limits.max_bind_groups, value),
287 "maxBindGroupsPlusVertexBuffers" => {
288 set_maximum(&mut limits.max_bind_groups_plus_vertex_buffers, value)
289 },
290 "maxImmediateSize" => set_maximum(&mut limits.max_immediate_size, value),
291 "maxBindingsPerBindGroup" => set_maximum(&mut limits.max_bindings_per_bind_group, value),
292 "maxDynamicUniformBuffersPerPipelineLayout" => set_maximum(
293 &mut limits.max_dynamic_uniform_buffers_per_pipeline_layout,
294 value,
295 ),
296 "maxDynamicStorageBuffersPerPipelineLayout" => set_maximum(
297 &mut limits.max_dynamic_storage_buffers_per_pipeline_layout,
298 value,
299 ),
300 "maxSampledTexturesPerShaderStage" => {
301 set_maximum(&mut limits.max_sampled_textures_per_shader_stage, value)
302 },
303 "maxSamplersPerShaderStage" => {
304 set_maximum(&mut limits.max_samplers_per_shader_stage, value)
305 },
306 "maxStorageBuffersPerShaderStage" => {
307 set_maximum(&mut limits.max_storage_buffers_per_shader_stage, value)
308 },
309 "maxStorageBuffersInVertexStage" => {
310 let mut v: u32 = 0;
314 set_maximum(&mut v, value)
315 },
316 "maxStorageBuffersInFragmentStage" => {
317 let mut v: u32 = 0;
321 set_maximum(&mut v, value)
322 },
323 "maxStorageTexturesPerShaderStage" => {
324 set_maximum(&mut limits.max_storage_textures_per_shader_stage, value)
325 },
326 "maxStorageTexturesInVertexStage" => {
327 let mut v: u32 = 0;
331 set_maximum(&mut v, value)
332 },
333 "maxStorageTexturesInFragmentStage" => {
334 let mut v: u32 = 0;
338 set_maximum(&mut v, value)
339 },
340 "maxUniformBuffersPerShaderStage" => {
341 set_maximum(&mut limits.max_uniform_buffers_per_shader_stage, value)
342 },
343 "maxUniformBufferBindingSize" => {
344 set_maximum(&mut limits.max_uniform_buffer_binding_size, value)
345 },
346 "maxStorageBufferBindingSize" => {
347 set_maximum(&mut limits.max_storage_buffer_binding_size, value)
348 },
349 "minUniformBufferOffsetAlignment" => {
350 set_alignment(&mut limits.min_uniform_buffer_offset_alignment, value)
351 },
352 "minStorageBufferOffsetAlignment" => {
353 set_alignment(&mut limits.min_storage_buffer_offset_alignment, value)
354 },
355 "maxVertexBuffers" => set_maximum(&mut limits.max_vertex_buffers, value),
356 "maxBufferSize" => set_maximum(&mut limits.max_buffer_size, value),
357 "maxVertexAttributes" => set_maximum(&mut limits.max_vertex_attributes, value),
358 "maxVertexBufferArrayStride" => {
359 set_maximum(&mut limits.max_vertex_buffer_array_stride, value)
360 },
361 "maxInterStageShaderVariables" => {
362 set_maximum(&mut limits.max_inter_stage_shader_variables, value)
363 },
364 "maxColorAttachments" => set_maximum(&mut limits.max_color_attachments, value),
365 "maxColorAttachmentBytesPerSample" => {
366 set_maximum(&mut limits.max_color_attachment_bytes_per_sample, value)
367 },
368 "maxComputeWorkgroupStorageSize" => {
369 set_maximum(&mut limits.max_compute_workgroup_storage_size, value)
370 },
371 "maxComputeInvocationsPerWorkgroup" => {
372 set_maximum(&mut limits.max_compute_invocations_per_workgroup, value)
373 },
374 "maxComputeWorkgroupSizeX" => set_maximum(&mut limits.max_compute_workgroup_size_x, value),
375 "maxComputeWorkgroupSizeY" => set_maximum(&mut limits.max_compute_workgroup_size_y, value),
376 "maxComputeWorkgroupSizeZ" => set_maximum(&mut limits.max_compute_workgroup_size_z, value),
377 "maxComputeWorkgroupsPerDimension" => {
378 set_maximum(&mut limits.max_compute_workgroups_per_dimension, value)
379 },
380 _ => false,
381 }
382}