wgpu/api/adapter.rs
1use alloc::vec::Vec;
2use core::future::Future;
3#[cfg(wgpu_core)]
4use core::ops::Deref;
5
6use crate::*;
7
8/// Handle to a physical graphics and/or compute device.
9///
10/// Adapters can be created using [`Instance::request_adapter`]
11/// or other [`Instance`] methods.
12///
13/// Adapters can be used to open a connection to the corresponding [`Device`]
14/// on the host system by using [`Adapter::request_device`].
15///
16/// Does not have to be kept alive.
17///
18/// Corresponds to [WebGPU `GPUAdapter`](https://gpuweb.github.io/gpuweb/#gpu-adapter).
19#[derive(Debug, Clone)]
20pub struct Adapter {
21 pub(crate) inner: dispatch::DispatchAdapter,
22}
23#[cfg(send_sync)]
24static_assertions::assert_impl_all!(Adapter: Send, Sync);
25
26crate::cmp::impl_eq_ord_hash_proxy!(Adapter => .inner);
27
28pub use wgt::RequestAdapterOptions as RequestAdapterOptionsBase;
29/// Additional information required when requesting an adapter.
30///
31/// For use with [`Instance::request_adapter`].
32///
33/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
34/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
35pub type RequestAdapterOptions<'a, 'b> = RequestAdapterOptionsBase<&'a Surface<'b>>;
36#[cfg(send_sync)]
37static_assertions::assert_impl_all!(RequestAdapterOptions<'_, '_>: Send, Sync);
38
39impl Adapter {
40 /// Requests a connection to a physical device, creating a logical device.
41 ///
42 /// Returns the [`Device`] together with a [`Queue`] that executes command buffers.
43 ///
44 /// [Per the WebGPU specification], an [`Adapter`] may only be used once to create a device.
45 /// If another device is wanted, call [`Instance::request_adapter()`] again to get a fresh
46 /// [`Adapter`].
47 /// However, `wgpu` does not currently enforce this restriction.
48 ///
49 /// # Panics
50 ///
51 /// - `request_device()` was already called on this `Adapter`.
52 /// - Features specified by `desc` are not supported by this adapter.
53 /// - Unsafe features were requested but not enabled when requesting the adapter.
54 /// - Limits requested exceed the values provided by the adapter.
55 /// - Adapter does not support all features wgpu requires to safely operate.
56 ///
57 /// [Per the WebGPU specification]: https://www.w3.org/TR/webgpu/#dom-gpuadapter-requestdevice
58 pub fn request_device(
59 &self,
60 desc: &DeviceDescriptor<'_>,
61 ) -> impl Future<Output = Result<(Device, Queue), RequestDeviceError>> + WasmNotSend {
62 let device = self.inner.request_device(desc);
63 async move {
64 device
65 .await
66 .map(|(device, queue)| (Device { inner: device }, Queue { inner: queue }))
67 }
68 }
69
70 /// Create a wgpu [`Device`] and [`Queue`] from a wgpu-hal [`hal::OpenDevice`].
71 ///
72 /// # Safety
73 ///
74 /// - `hal_device` must be created from this adapter internal handle.
75 /// - `desc.features` must be a subset of `hal_device`'s supported features.
76 #[cfg(wgpu_core)]
77 pub unsafe fn create_device_from_hal<A: hal::Api>(
78 &self,
79 hal_device: hal::OpenDevice<A>,
80 desc: &DeviceDescriptor<'_>,
81 ) -> Result<(Device, Queue), RequestDeviceError> {
82 let core_adapter = self.inner.as_core();
83 let (device, queue) = unsafe {
84 core_adapter
85 .context
86 .create_device_from_hal(core_adapter, hal_device, desc)
87 }?;
88
89 Ok((
90 Device {
91 inner: device.into(),
92 },
93 Queue {
94 inner: queue.into(),
95 },
96 ))
97 }
98
99 /// Get the [`wgpu_hal`] adapter from this `Adapter`.
100 ///
101 /// Find the Api struct corresponding to the active backend in [`wgpu_hal::api`],
102 /// and pass that struct to the to the `A` type parameter.
103 ///
104 /// Returns a guard that dereferences to the type of the hal backend
105 /// which implements [`A::Adapter`].
106 ///
107 /// # Types
108 ///
109 /// The returned type depends on the backend:
110 ///
111 #[doc = crate::hal_type_vulkan!("Adapter")]
112 #[doc = crate::hal_type_metal!("Adapter")]
113 #[doc = crate::hal_type_dx12!("Adapter")]
114 #[doc = crate::hal_type_gles!("Adapter")]
115 ///
116 /// # Errors
117 ///
118 /// This method will return None if:
119 /// - The adapter is not from the backend specified by `A`.
120 /// - The adapter is from the `webgpu` or `custom` backend.
121 ///
122 /// # Safety
123 ///
124 /// - The returned resource must not be destroyed unless the guard
125 /// is the last reference to it and it is not in use by the GPU.
126 /// The guard and handle may be dropped at any time however.
127 /// - All the safety requirements of wgpu-hal must be upheld.
128 ///
129 /// [`A::Adapter`]: hal::Api::Adapter
130 #[cfg(wgpu_core)]
131 pub unsafe fn as_hal<A: hal::Api>(
132 &self,
133 ) -> Option<impl Deref<Target = A::Adapter> + WasmNotSendSync> {
134 let adapter = self.inner.as_core_opt()?;
135
136 unsafe { adapter.context.adapter_as_hal::<A>(adapter) }
137 }
138
139 #[cfg(custom)]
140 /// Returns custom implementation of adapter (if custom backend and is internally T)
141 pub fn as_custom<T: custom::AdapterInterface>(&self) -> Option<&T> {
142 self.inner.as_custom()
143 }
144
145 #[cfg(custom)]
146 /// Creates Adapter from custom implementation
147 pub fn from_custom<T: custom::AdapterInterface>(adapter: T) -> Self {
148 Self {
149 inner: dispatch::DispatchAdapter::custom(adapter),
150 }
151 }
152
153 /// Returns whether this adapter may present to the passed surface.
154 pub fn is_surface_supported(&self, surface: &Surface<'_>) -> bool {
155 self.inner.is_surface_supported(&surface.inner)
156 }
157
158 /// The features which can be used to create devices on this adapter.
159 pub fn features(&self) -> Features {
160 self.inner.features()
161 }
162
163 /// The best limits which can be used to create devices on this adapter.
164 pub fn limits(&self) -> Limits {
165 self.inner.limits()
166 }
167
168 /// Get info about the adapter itself.
169 pub fn get_info(&self) -> AdapterInfo {
170 self.inner.get_info()
171 }
172
173 /// Get info about the adapter itself.
174 pub fn get_downlevel_capabilities(&self) -> DownlevelCapabilities {
175 self.inner.downlevel_capabilities()
176 }
177
178 /// Returns the features supported for a given texture format by this adapter.
179 ///
180 /// Note that the WebGPU spec further restricts the available usages/features.
181 /// To disable these restrictions on a device, request the [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] feature.
182 pub fn get_texture_format_features(&self, format: TextureFormat) -> TextureFormatFeatures {
183 self.inner.get_texture_format_features(format)
184 }
185
186 /// Generates a timestamp using the clock used by the presentation engine.
187 ///
188 /// When comparing completely opaque timestamp systems, we need a way of generating timestamps that signal
189 /// the exact same time. You can do this by calling your own timestamp function immediately after a call to
190 /// this function. This should result in timestamps that are 0.5 to 5 microseconds apart. There are locks
191 /// that must be taken during the call, so don't call your function before.
192 ///
193 /// ```no_run
194 /// # let adapter: wgpu::Adapter = panic!();
195 /// # let some_code = || wgpu::PresentationTimestamp::INVALID_TIMESTAMP;
196 /// use std::time::{Duration, Instant};
197 /// let presentation = adapter.get_presentation_timestamp();
198 /// let instant = Instant::now();
199 ///
200 /// // We can now turn a new presentation timestamp into an Instant.
201 /// let some_pres_timestamp = some_code();
202 /// let duration = Duration::from_nanos((some_pres_timestamp.0 - presentation.0) as u64);
203 /// let new_instant: Instant = instant + duration;
204 /// ```
205 //
206 /// [Instant]: std::time::Instant
207 pub fn get_presentation_timestamp(&self) -> PresentationTimestamp {
208 self.inner.get_presentation_timestamp()
209 }
210
211 /// Returns the supported cooperative matrix configurations for this adapter.
212 ///
213 /// Cooperative matrices enable hardware-accelerated matrix multiply-accumulate
214 /// operations where threads in a subgroup collectively process matrix tiles.
215 ///
216 /// Returns an empty vector if cooperative matrices are not supported.
217 ///
218 /// Requires [`Features::EXPERIMENTAL_COOPERATIVE_MATRIX`] to be meaningful.
219 #[cfg(wgpu_core)]
220 pub fn cooperative_matrix_properties(&self) -> Vec<CooperativeMatrixProperties> {
221 self.inner.cooperative_matrix_properties()
222 }
223}