wgpu_types/adapter.rs
1use alloc::string::String;
2use core::{fmt, mem};
3
4use crate::{link_to_wgpu_docs, Backend, Backends};
5
6#[cfg(any(feature = "serde", test))]
7use serde::{Deserialize, Serialize};
8
9#[cfg(doc)]
10use crate::{Features, TextureUsages};
11
12/// A set of requested capabilities when choosing a physical adapter.
13///
14/// Corresponds to the defined values of [WebGPU feature level string](
15/// https://gpuweb.github.io/gpuweb/#feature-level-string).
16///
17/// `wgpu` does not support compatibility-level adapters per se.
18#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
21pub enum FeatureLevel {
22 #[default]
23 /// The `core` capability set
24 Core,
25 /// The `compatibility` capability set
26 Compatibility,
27}
28
29/// Options for requesting adapter.
30///
31/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
32/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
33#[repr(C)]
34#[derive(Clone, Debug, PartialEq, Eq, Hash)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36pub struct RequestAdapterOptions<S> {
37 /// Power preference for the adapter.
38 pub power_preference: PowerPreference,
39 /// Indicates that only a fallback adapter can be returned. This is generally a "software"
40 /// implementation on the system.
41 pub force_fallback_adapter: bool,
42 /// Surface that is required to be presentable with the requested adapter. This does not
43 /// create the surface, only guarantees that the adapter can present to said surface.
44 /// For WebGL, this is strictly required, as an adapter can not be created without a surface.
45 pub compatible_surface: Option<S>,
46}
47
48impl<S> Default for RequestAdapterOptions<S> {
49 fn default() -> Self {
50 Self {
51 power_preference: PowerPreference::default(),
52 force_fallback_adapter: false,
53 compatible_surface: None,
54 }
55 }
56}
57
58/// Power Preference when choosing a physical adapter.
59///
60/// Corresponds to [WebGPU `GPUPowerPreference`](
61/// https://gpuweb.github.io/gpuweb/#enumdef-gpupowerpreference).
62#[repr(C)]
63#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
66pub enum PowerPreference {
67 #[default]
68 /// Power usage is not considered when choosing an adapter.
69 None = 0,
70 /// Adapter that uses the least possible power. This is often an integrated GPU.
71 LowPower = 1,
72 /// Adapter that has the highest performance. This is often a discrete GPU.
73 HighPerformance = 2,
74}
75
76impl PowerPreference {
77 /// Get a power preference from the environment variable `WGPU_POWER_PREF`.
78 pub fn from_env() -> Option<Self> {
79 let env = crate::env::var("WGPU_POWER_PREF")?;
80 match env.to_lowercase().as_str() {
81 "low" => Some(Self::LowPower),
82 "high" => Some(Self::HighPerformance),
83 "none" => Some(Self::None),
84 _ => None,
85 }
86 }
87}
88
89/// Supported physical device types.
90#[repr(u8)]
91#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
92#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
93pub enum DeviceType {
94 /// Other or Unknown.
95 Other,
96 /// Integrated GPU with shared CPU/GPU memory.
97 IntegratedGpu,
98 /// Discrete GPU with separate CPU/GPU memory.
99 DiscreteGpu,
100 /// Virtual / Hosted.
101 VirtualGpu,
102 /// Cpu / Software Rendering.
103 Cpu,
104}
105
106//TODO: convert `vendor` and `device` to `u32`
107
108/// Information about an adapter.
109#[derive(Clone, Debug, Eq, PartialEq, Hash)]
110#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
111pub struct AdapterInfo {
112 /// Adapter name
113 pub name: String,
114 /// [`Backend`]-specific vendor ID of the adapter
115 ///
116 /// This generally is a 16-bit PCI vendor ID in the least significant bytes of this field.
117 /// However, more significant bytes may be non-zero if the backend uses a different
118 /// representation.
119 ///
120 /// * For [`Backend::Vulkan`], the [`VkPhysicalDeviceProperties::vendorID`] is used, which is
121 /// a superset of PCI IDs.
122 ///
123 /// [`VkPhysicalDeviceProperties::vendorID`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
124 pub vendor: u32,
125 /// [`Backend`]-specific device ID of the adapter
126 ///
127 ///
128 /// This generally is a 16-bit PCI device ID in the least significant bytes of this field.
129 /// However, more significant bytes may be non-zero if the backend uses a different
130 /// representation.
131 ///
132 /// * For [`Backend::Vulkan`], the [`VkPhysicalDeviceProperties::deviceID`] is used, which is
133 /// a superset of PCI IDs.
134 ///
135 /// [`VkPhysicalDeviceProperties::deviceID`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
136 pub device: u32,
137 /// Type of device
138 pub device_type: DeviceType,
139 /// [`Backend`]-specific PCI bus ID of the adapter.
140 ///
141 /// * For [`Backend::Vulkan`], [`VkPhysicalDevicePCIBusInfoPropertiesEXT`] is used,
142 /// if available, in the form `bus:device.function`, e.g. `0000:01:00.0`.
143 ///
144 /// [`VkPhysicalDevicePCIBusInfoPropertiesEXT`]: https://registry.khronos.org/vulkan/specs/latest/man/html/VkPhysicalDevicePCIBusInfoPropertiesEXT.html
145 pub device_pci_bus_id: String,
146 /// Driver name
147 pub driver: String,
148 /// Driver info
149 pub driver_info: String,
150 /// Backend used for device
151 pub backend: Backend,
152 /// Minimum possible size of a subgroup on this adapter. Will
153 /// never be lower than [`crate::MINIMUM_SUBGROUP_MIN_SIZE`].
154 ///
155 /// This will vary from device to device. Typical values are listed below.
156 ///
157 /// - NVIDIA: 32
158 /// - AMD GCN/Vega: 64
159 /// - AMD RDNA+: 32
160 /// - Intel: 8 or 16
161 /// - Qualcomm: 64
162 /// - WARP: 4
163 /// - lavapipe: 8
164 pub subgroup_min_size: u32,
165 /// Maximum possible size of a subgroup on this adapter. Will
166 /// never be higher than [`crate::MAXIMUM_SUBGROUP_MAX_SIZE`].
167 ///
168 /// This will vary from device to device. Typical values are listed below:
169 ///
170 /// - NVIDIA: 32
171 /// - AMD GCN/Vega: 64
172 /// - AMD RDNA+: 64
173 /// - Intel: 16 or 32
174 /// - Qualcomm: 128
175 /// - WARP: 4 or 128
176 /// - lavapipe: 8
177 pub subgroup_max_size: u32,
178 /// If true, adding [`TextureUsages::TRANSIENT`] to a texture will decrease memory usage.
179 pub transient_saves_memory: bool,
180}
181
182/// Error when [`Instance::request_adapter()`] fails.
183///
184/// This type is not part of the WebGPU standard, where `requestAdapter()` would simply return null.
185///
186#[doc = link_to_wgpu_docs!(["`Instance::request_adapter()`"]: "struct.Instance.html#method.request_adapter")]
187#[derive(Clone, Debug, PartialEq)]
188#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
189#[non_exhaustive]
190pub enum RequestAdapterError {
191 /// No adapter available via the instance’s backends matched the request’s adapter criteria.
192 NotFound {
193 // These fields must be set by wgpu-core and wgpu, but are not intended to be stable API,
194 // only data for the production of the error message.
195 #[doc(hidden)]
196 active_backends: Backends,
197 #[doc(hidden)]
198 requested_backends: Backends,
199 #[doc(hidden)]
200 supported_backends: Backends,
201 #[doc(hidden)]
202 no_fallback_backends: Backends,
203 #[doc(hidden)]
204 no_adapter_backends: Backends,
205 #[doc(hidden)]
206 incompatible_surface_backends: Backends,
207 },
208
209 /// Attempted to obtain adapter specified by environment variable, but the environment variable
210 /// was not set.
211 EnvNotSet,
212}
213
214impl core::error::Error for RequestAdapterError {}
215impl fmt::Display for RequestAdapterError {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 match self {
218 RequestAdapterError::NotFound {
219 active_backends,
220 requested_backends,
221 supported_backends,
222 no_fallback_backends,
223 no_adapter_backends,
224 incompatible_surface_backends,
225 } => {
226 write!(f, "No suitable graphics adapter found; ")?;
227 let mut first = true;
228 for backend in Backend::ALL {
229 let bit = Backends::from(backend);
230 let comma = if mem::take(&mut first) { "" } else { ", " };
231 let explanation = if !requested_backends.contains(bit) {
232 // We prefer reporting this, because it makes the error most stable with
233 // respect to what is directly controllable by the caller, as opposed to
234 // compilation options or the run-time environment.
235 "not requested"
236 } else if !supported_backends.contains(bit) {
237 "support not compiled in"
238 } else if no_adapter_backends.contains(bit) {
239 "found no adapters"
240 } else if incompatible_surface_backends.contains(bit) {
241 "not compatible with provided surface"
242 } else if no_fallback_backends.contains(bit) {
243 "had no fallback adapters"
244 } else if !active_backends.contains(bit) {
245 // Backend requested but not active in this instance
246 if backend == Backend::Noop {
247 "not explicitly enabled"
248 } else {
249 "drivers/libraries could not be loaded"
250 }
251 } else {
252 // This path should be unreachable, but don't crash.
253 "[unknown reason]"
254 };
255 write!(f, "{comma}{backend} {explanation}")?;
256 }
257 }
258 RequestAdapterError::EnvNotSet => f.write_str("WGPU_ADAPTER_NAME not set")?,
259 }
260 Ok(())
261 }
262}
263
264/// The underlying scalar type of the cooperative matrix component.
265#[repr(u8)]
266#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
267#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
268pub enum CooperativeScalarType {
269 /// 32-bit floating point.
270 F32,
271 /// 16-bit floating point.
272 F16,
273 /// 32-bit signed integer.
274 I32,
275 /// 32-bit unsigned integer.
276 U32,
277}
278
279/// Describes a supported cooperative matrix configuration.
280///
281/// Cooperative matrices perform the operation `C = A * B + C` where:
282/// - `A` is an M×K matrix
283/// - `B` is a K×N matrix
284/// - `C` is an M×N matrix (both input accumulator and output)
285#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
286pub struct CooperativeMatrixProperties {
287 /// Number of rows in matrices A and C (M dimension)
288 pub m_size: u32,
289 /// Number of columns in matrices B and C (N dimension)
290 pub n_size: u32,
291 /// Number of columns in A / rows in B (K dimension)
292 pub k_size: u32,
293 /// Element type for input matrices A and B
294 pub ab_type: CooperativeScalarType,
295 /// Element type for accumulator matrix C and the result
296 pub cr_type: CooperativeScalarType,
297 /// Whether saturating accumulation is supported.
298 ///
299 /// When true, the multiply-add operation clamps the result to prevent overflow.
300 pub saturating_accumulation: bool,
301}