1#[cfg(any(dx12, all(vulkan, windows)))]
5pub(super) mod dxgi;
6
7#[cfg(all(native, feature = "renderdoc"))]
8pub(super) mod renderdoc;
9
10pub mod prune;
11
12pub mod db {
13 pub mod amd {
14 pub const VENDOR: u32 = 0x1002;
16 }
17 pub mod apple {
18 pub const VENDOR: u32 = 0x106B;
20 }
21 pub mod arm {
22 pub const VENDOR: u32 = 0x13B5;
24 }
25 pub mod broadcom {
26 pub const VENDOR: u32 = 0x14E4;
28 }
29 pub mod imgtec {
30 pub const VENDOR: u32 = 0x1010;
32 }
33 pub mod intel {
34 pub const VENDOR: u32 = 0x8086;
36 pub const DEVICE_KABY_LAKE_MASK: u32 = 0x5900;
37 pub const DEVICE_SKY_LAKE_MASK: u32 = 0x1900;
38 }
39 pub mod mesa {
40 pub const VENDOR: u32 = 0x10005;
46 }
47 pub mod nvidia {
48 pub const VENDOR: u32 = 0x10DE;
50 }
51 pub mod qualcomm {
52 pub const VENDOR: u32 = 0x5143;
54 }
55}
56
57pub const MAX_I32_BINDING_SIZE: u32 = (1 << 31) - 1;
62
63pub use wgpu_naga_bridge::map_naga_stage;
64
65impl crate::CopyExtent {
66 pub fn map_extent_to_copy_size(extent: &wgt::Extent3d, dim: wgt::TextureDimension) -> Self {
67 Self {
68 width: extent.width,
69 height: extent.height,
70 depth: match dim {
71 wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => 1,
72 wgt::TextureDimension::D3 => extent.depth_or_array_layers,
73 },
74 }
75 }
76
77 pub fn min(&self, other: &Self) -> Self {
78 Self {
79 width: self.width.min(other.width),
80 height: self.height.min(other.height),
81 depth: self.depth.min(other.depth),
82 }
83 }
84
85 pub fn at_mip_level(&self, level: u32) -> Self {
89 Self {
90 width: (self.width >> level).max(1),
91 height: (self.height >> level).max(1),
92 depth: (self.depth >> level).max(1),
93 }
94 }
95}
96
97impl crate::TextureCopyBase {
98 pub fn max_copy_size(&self, full_size: &crate::CopyExtent) -> crate::CopyExtent {
99 let mip = full_size.at_mip_level(self.mip_level);
100 crate::CopyExtent {
101 width: mip.width - self.origin.x,
102 height: mip.height - self.origin.y,
103 depth: mip.depth - self.origin.z,
104 }
105 }
106}
107
108impl crate::BufferTextureCopy {
109 pub fn clamp_size_to_virtual(&mut self, full_size: &crate::CopyExtent) {
110 let max_size = self.texture_base.max_copy_size(full_size);
111 self.size = self.size.min(&max_size);
112 }
113}
114
115impl crate::TextureCopy {
116 pub fn clamp_size_to_virtual(
117 &mut self,
118 full_src_size: &crate::CopyExtent,
119 full_dst_size: &crate::CopyExtent,
120 ) {
121 let max_src_size = self.src_base.max_copy_size(full_src_size);
122 let max_dst_size = self.dst_base.max_copy_size(full_dst_size);
123 self.size = self.size.min(&max_src_size).min(&max_dst_size);
124 }
125}
126
127#[cfg_attr(not(any_backend), allow(dead_code))]
130pub(crate) fn adjust_raw_limits(mut limits: wgt::Limits) -> wgt::Limits {
131 limits.max_bind_groups = limits.max_bind_groups.min(crate::MAX_BIND_GROUPS as u32);
133 limits.max_vertex_buffers = limits
134 .max_vertex_buffers
135 .min(crate::MAX_VERTEX_BUFFERS as u32);
136 const { assert!(crate::MAX_BIND_GROUPS + crate::MAX_VERTEX_BUFFERS == 24) };
140 limits.max_bind_groups_plus_vertex_buffers = limits.max_bind_groups_plus_vertex_buffers.min(24);
141 limits.max_color_attachments = limits
142 .max_color_attachments
143 .min(crate::MAX_COLOR_ATTACHMENTS as u32);
144
145 const MAX_SHADER_STAGES_PER_PIPELINE: u32 = 2;
154 let max_per_stage_resources =
155 limits.max_bindings_per_bind_group / MAX_SHADER_STAGES_PER_PIPELINE;
156
157 cap_limits_to_be_under_the_sum_limit(
158 [
159 &mut limits.max_sampled_textures_per_shader_stage,
160 &mut limits.max_uniform_buffers_per_shader_stage,
161 &mut limits.max_storage_textures_per_shader_stage,
162 &mut limits.max_storage_buffers_per_shader_stage,
163 &mut limits.max_samplers_per_shader_stage,
164 &mut limits.max_acceleration_structures_per_shader_stage,
165 ],
166 max_per_stage_resources,
167 );
168
169 limits.max_dynamic_uniform_buffers_per_pipeline_layout = limits
172 .max_dynamic_uniform_buffers_per_pipeline_layout
173 .min(limits.max_uniform_buffers_per_shader_stage);
174 limits.max_dynamic_storage_buffers_per_pipeline_layout = limits
175 .max_dynamic_storage_buffers_per_pipeline_layout
176 .min(limits.max_storage_buffers_per_shader_stage);
177
178 limits.min_uniform_buffer_offset_alignment = limits.min_uniform_buffer_offset_alignment.max(32);
179 limits.min_storage_buffer_offset_alignment = limits.min_storage_buffer_offset_alignment.max(32);
180
181 limits.max_uniform_buffer_binding_size = limits
182 .max_uniform_buffer_binding_size
183 .min(limits.max_buffer_size);
184 limits.max_storage_buffer_binding_size = limits
185 .max_storage_buffer_binding_size
186 .min(limits.max_buffer_size);
187
188 limits.max_storage_buffer_binding_size &= !(u64::from(wgt::STORAGE_BINDING_SIZE_ALIGNMENT) - 1);
189 limits.max_vertex_buffer_array_stride &= !(wgt::VERTEX_ALIGNMENT as u32 - 1);
190
191 let x = limits.max_compute_workgroup_size_x;
192 let y = limits.max_compute_workgroup_size_y;
193 let z = limits.max_compute_workgroup_size_z;
194 let m = limits.max_compute_invocations_per_workgroup;
195 limits.max_compute_workgroup_size_x = x.min(m);
196 limits.max_compute_workgroup_size_y = y.min(m);
197 limits.max_compute_workgroup_size_z = z.min(m);
198 limits.max_compute_invocations_per_workgroup = m.min(x.saturating_mul(y).saturating_mul(z));
199
200 limits.max_immediate_size = limits.max_immediate_size.min(256);
201
202 limits
203}
204
205pub fn cap_limits_to_be_under_the_sum_limit<const N: usize>(
208 mut limits: [&mut u32; N],
209 sum_limit: u32,
210) {
211 limits.sort();
212
213 let mut rem_limit = sum_limit;
214 let mut divisor = limits.len() as u32;
215 for limit_to_adjust in limits {
216 let limit = rem_limit / divisor;
217 *limit_to_adjust = (*limit_to_adjust).min(limit);
218 rem_limit -= *limit_to_adjust;
219 divisor -= 1;
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226
227 #[test]
228 fn test_cap_limits_to_be_under_the_sum_limit() {
229 test([3, 3, 3], 3, [1, 1, 1]);
230 test([3, 2, 1], 3, [1, 1, 1]);
231 test([1, 2, 3], 6, [1, 2, 3]);
232 test([1, 2, 3], 3, [1, 1, 1]);
233 test([1, 8, 100], 6, [1, 2, 3]);
234 test([2, 80, 80], 6, [2, 2, 2]);
235 test([2, 80, 80], 12, [2, 5, 5]);
236
237 #[track_caller]
238 fn test<const N: usize>(mut input: [u32; N], limit: u32, output: [u32; N]) {
239 cap_limits_to_be_under_the_sum_limit(input.each_mut(), limit);
240 assert_eq!(input, output);
241 }
242 }
243}