wgpu_hal/auxil/
mod.rs

1#[cfg(dx12)]
2pub(super) mod dxgi;
3
4#[cfg(all(native, feature = "renderdoc"))]
5pub(super) mod renderdoc;
6
7pub mod db {
8    pub mod amd {
9        /// cbindgen:ignore
10        pub const VENDOR: u32 = 0x1002;
11    }
12    pub mod apple {
13        /// cbindgen:ignore
14        pub const VENDOR: u32 = 0x106B;
15    }
16    pub mod arm {
17        /// cbindgen:ignore
18        pub const VENDOR: u32 = 0x13B5;
19    }
20    pub mod broadcom {
21        /// cbindgen:ignore
22        pub const VENDOR: u32 = 0x14E4;
23    }
24    pub mod imgtec {
25        /// cbindgen:ignore
26        pub const VENDOR: u32 = 0x1010;
27    }
28    pub mod intel {
29        /// cbindgen:ignore
30        pub const VENDOR: u32 = 0x8086;
31        pub const DEVICE_KABY_LAKE_MASK: u32 = 0x5900;
32        pub const DEVICE_SKY_LAKE_MASK: u32 = 0x1900;
33    }
34    pub mod mesa {
35        // Mesa does not actually have a PCI vendor id.
36        //
37        // To match Vulkan, we use the VkVendorId for Mesa in the gles backend so that lavapipe (Vulkan) and
38        // llvmpipe (OpenGL) have the same vendor id.
39        /// cbindgen:ignore
40        pub const VENDOR: u32 = 0x10005;
41    }
42    pub mod nvidia {
43        /// cbindgen:ignore
44        pub const VENDOR: u32 = 0x10DE;
45    }
46    pub mod qualcomm {
47        /// cbindgen:ignore
48        pub const VENDOR: u32 = 0x5143;
49    }
50}
51
52/// Maximum binding size for the shaders that only support `i32` indexing.
53/// Interestingly, the index itself can't reach that high, because the minimum
54/// element size is 4 bytes, but the compiler toolchain still computes the
55/// offset at some intermediate point, internally, as i32.
56pub const MAX_I32_BINDING_SIZE: u32 = (1 << 31) - 1;
57
58pub fn map_naga_stage(stage: naga::ShaderStage) -> wgt::ShaderStages {
59    match stage {
60        naga::ShaderStage::Vertex => wgt::ShaderStages::VERTEX,
61        naga::ShaderStage::Fragment => wgt::ShaderStages::FRAGMENT,
62        naga::ShaderStage::Compute => wgt::ShaderStages::COMPUTE,
63        naga::ShaderStage::Task => wgt::ShaderStages::TASK,
64        naga::ShaderStage::Mesh => wgt::ShaderStages::MESH,
65        naga::ShaderStage::RayGeneration => wgt::ShaderStages::RAY_GENERATION,
66        naga::ShaderStage::AnyHit => wgt::ShaderStages::ANY_HIT,
67        naga::ShaderStage::ClosestHit => wgt::ShaderStages::CLOSEST_HIT,
68        naga::ShaderStage::Miss => wgt::ShaderStages::MISS,
69    }
70}
71
72impl crate::CopyExtent {
73    pub fn map_extent_to_copy_size(extent: &wgt::Extent3d, dim: wgt::TextureDimension) -> Self {
74        Self {
75            width: extent.width,
76            height: extent.height,
77            depth: match dim {
78                wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => 1,
79                wgt::TextureDimension::D3 => extent.depth_or_array_layers,
80            },
81        }
82    }
83
84    pub fn min(&self, other: &Self) -> Self {
85        Self {
86            width: self.width.min(other.width),
87            height: self.height.min(other.height),
88            depth: self.depth.min(other.depth),
89        }
90    }
91
92    // Get the copy size at a specific mipmap level. This doesn't make most sense,
93    // since the copy extents are provided *for* a mipmap level to start with.
94    // But backends use `CopyExtent` more sparingly, and this piece is shared.
95    pub fn at_mip_level(&self, level: u32) -> Self {
96        Self {
97            width: (self.width >> level).max(1),
98            height: (self.height >> level).max(1),
99            depth: (self.depth >> level).max(1),
100        }
101    }
102}
103
104impl crate::TextureCopyBase {
105    pub fn max_copy_size(&self, full_size: &crate::CopyExtent) -> crate::CopyExtent {
106        let mip = full_size.at_mip_level(self.mip_level);
107        crate::CopyExtent {
108            width: mip.width - self.origin.x,
109            height: mip.height - self.origin.y,
110            depth: mip.depth - self.origin.z,
111        }
112    }
113}
114
115impl crate::BufferTextureCopy {
116    pub fn clamp_size_to_virtual(&mut self, full_size: &crate::CopyExtent) {
117        let max_size = self.texture_base.max_copy_size(full_size);
118        self.size = self.size.min(&max_size);
119    }
120}
121
122impl crate::TextureCopy {
123    pub fn clamp_size_to_virtual(
124        &mut self,
125        full_src_size: &crate::CopyExtent,
126        full_dst_size: &crate::CopyExtent,
127    ) {
128        let max_src_size = self.src_base.max_copy_size(full_src_size);
129        let max_dst_size = self.dst_base.max_copy_size(full_dst_size);
130        self.size = self.size.min(&max_src_size).min(&max_dst_size);
131    }
132}
133
134/// Clamp the limits in `limits` to honor HAL-imposed maximums and WebGPU
135/// alignment requirements.
136///
137/// Other limits are left unchanged.
138#[cfg_attr(not(any_backend), allow(dead_code))]
139pub(crate) fn apply_hal_limits(mut limits: wgt::Limits) -> wgt::Limits {
140    // The Metal backend maintains two copies of many limit values (one as
141    // `wgt::Limits` and one as `metal::PrivateCapabilities`). In order to avoid
142    // confusing discrepancies between the two, some of the logic here is
143    // duplicated in the initialization of `metal::PrivateCapabilities`.
144    // See <https://github.com/gfx-rs/wgpu/issues/8715>.
145
146    limits.max_bind_groups = limits.max_bind_groups.min(crate::MAX_BIND_GROUPS as u32);
147    limits.max_vertex_buffers = limits
148        .max_vertex_buffers
149        .min(crate::MAX_VERTEX_BUFFERS as u32);
150    limits.max_color_attachments = limits
151        .max_color_attachments
152        .min(crate::MAX_COLOR_ATTACHMENTS as u32);
153
154    // Round some limits down to the WebGPU alignment requirement, to avoid
155    // suggesting values that won't work. (In particular, the CTS queries limits
156    // and then tests the exact limit value.)
157    limits.max_storage_buffer_binding_size &= !(wgt::STORAGE_BINDING_SIZE_ALIGNMENT - 1);
158    limits.max_vertex_buffer_array_stride &= !(wgt::VERTEX_ALIGNMENT as u32 - 1);
159
160    limits
161}