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