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