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