Skip to content

Commit 164b7bd

Browse files
authored
Split wgpu Crate into Modules (#5998)
* Split wgpu/lib.rs into Modules * Use crate::* Imports
1 parent cf57982 commit 164b7bd

30 files changed

+6247
-6054
lines changed

wgpu/src/api/adapter.rs

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
use std::{future::Future, sync::Arc, thread};
2+
3+
use crate::context::{DeviceRequest, DynContext, ObjectId};
4+
use crate::*;
5+
6+
/// Handle to a physical graphics and/or compute device.
7+
///
8+
/// Adapters can be used to open a connection to the corresponding [`Device`]
9+
/// on the host system by using [`Adapter::request_device`].
10+
///
11+
/// Does not have to be kept alive.
12+
///
13+
/// Corresponds to [WebGPU `GPUAdapter`](https://gpuweb.github.io/gpuweb/#gpu-adapter).
14+
#[derive(Debug)]
15+
pub struct Adapter {
16+
pub(crate) context: Arc<C>,
17+
pub(crate) id: ObjectId,
18+
pub(crate) data: Box<Data>,
19+
}
20+
#[cfg(send_sync)]
21+
static_assertions::assert_impl_all!(Adapter: Send, Sync);
22+
23+
impl Drop for Adapter {
24+
fn drop(&mut self) {
25+
if !thread::panicking() {
26+
self.context.adapter_drop(&self.id, self.data.as_ref())
27+
}
28+
}
29+
}
30+
31+
pub use wgt::RequestAdapterOptions as RequestAdapterOptionsBase;
32+
/// Additional information required when requesting an adapter.
33+
///
34+
/// For use with [`Instance::request_adapter`].
35+
///
36+
/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
37+
/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
38+
pub type RequestAdapterOptions<'a, 'b> = RequestAdapterOptionsBase<&'a Surface<'b>>;
39+
#[cfg(send_sync)]
40+
static_assertions::assert_impl_all!(RequestAdapterOptions<'_, '_>: Send, Sync);
41+
42+
impl Adapter {
43+
/// Returns a globally-unique identifier for this `Adapter`.
44+
///
45+
/// Calling this method multiple times on the same object will always return the same value.
46+
/// The returned value is guaranteed to be different for all resources created from the same `Instance`.
47+
pub fn global_id(&self) -> Id<Self> {
48+
Id::new(self.id)
49+
}
50+
51+
/// Requests a connection to a physical device, creating a logical device.
52+
///
53+
/// Returns the [`Device`] together with a [`Queue`] that executes command buffers.
54+
///
55+
/// [Per the WebGPU specification], an [`Adapter`] may only be used once to create a device.
56+
/// If another device is wanted, call [`Instance::request_adapter()`] again to get a fresh
57+
/// [`Adapter`].
58+
/// However, `wgpu` does not currently enforce this restriction.
59+
///
60+
/// # Arguments
61+
///
62+
/// - `desc` - Description of the features and limits requested from the given device.
63+
/// - `trace_path` - Can be used for API call tracing, if that feature is
64+
/// enabled in `wgpu-core`.
65+
///
66+
/// # Panics
67+
///
68+
/// - `request_device()` was already called on this `Adapter`.
69+
/// - Features specified by `desc` are not supported by this adapter.
70+
/// - Unsafe features were requested but not enabled when requesting the adapter.
71+
/// - Limits requested exceed the values provided by the adapter.
72+
/// - Adapter does not support all features wgpu requires to safely operate.
73+
///
74+
/// [Per the WebGPU specification]: https://www.w3.org/TR/webgpu/#dom-gpuadapter-requestdevice
75+
pub fn request_device(
76+
&self,
77+
desc: &DeviceDescriptor<'_>,
78+
trace_path: Option<&std::path::Path>,
79+
) -> impl Future<Output = Result<(Device, Queue), RequestDeviceError>> + WasmNotSend {
80+
let context = Arc::clone(&self.context);
81+
let device = DynContext::adapter_request_device(
82+
&*self.context,
83+
&self.id,
84+
self.data.as_ref(),
85+
desc,
86+
trace_path,
87+
);
88+
async move {
89+
device.await.map(
90+
|DeviceRequest {
91+
device_id,
92+
device_data,
93+
queue_id,
94+
queue_data,
95+
}| {
96+
(
97+
Device {
98+
context: Arc::clone(&context),
99+
id: device_id,
100+
data: device_data,
101+
},
102+
Queue {
103+
context,
104+
id: queue_id,
105+
data: queue_data,
106+
},
107+
)
108+
},
109+
)
110+
}
111+
}
112+
113+
/// Create a wgpu [`Device`] and [`Queue`] from a wgpu-hal `OpenDevice`
114+
///
115+
/// # Safety
116+
///
117+
/// - `hal_device` must be created from this adapter internal handle.
118+
/// - `desc.features` must be a subset of `hal_device` features.
119+
#[cfg(wgpu_core)]
120+
pub unsafe fn create_device_from_hal<A: wgc::hal_api::HalApi>(
121+
&self,
122+
hal_device: hal::OpenDevice<A>,
123+
desc: &DeviceDescriptor<'_>,
124+
trace_path: Option<&std::path::Path>,
125+
) -> Result<(Device, Queue), RequestDeviceError> {
126+
let context = Arc::clone(&self.context);
127+
unsafe {
128+
self.context
129+
.as_any()
130+
.downcast_ref::<crate::backend::ContextWgpuCore>()
131+
// Part of the safety requirements is that the device was generated from the same adapter.
132+
// Therefore, unwrap is fine here since only WgpuCoreContext based adapters have the ability to create hal devices.
133+
.unwrap()
134+
.create_device_from_hal(&self.id.into(), hal_device, desc, trace_path)
135+
}
136+
.map(|(device, queue)| {
137+
(
138+
Device {
139+
context: Arc::clone(&context),
140+
id: device.id().into(),
141+
data: Box::new(device),
142+
},
143+
Queue {
144+
context,
145+
id: queue.id().into(),
146+
data: Box::new(queue),
147+
},
148+
)
149+
})
150+
}
151+
152+
/// Apply a callback to this `Adapter`'s underlying backend adapter.
153+
///
154+
/// If this `Adapter` is implemented by the backend API given by `A` (Vulkan,
155+
/// Dx12, etc.), then apply `hal_adapter_callback` to `Some(&adapter)`, where
156+
/// `adapter` is the underlying backend adapter type, [`A::Adapter`].
157+
///
158+
/// If this `Adapter` uses a different backend, apply `hal_adapter_callback`
159+
/// to `None`.
160+
///
161+
/// The adapter is locked for reading while `hal_adapter_callback` runs. If
162+
/// the callback attempts to perform any `wgpu` operations that require
163+
/// write access to the adapter, deadlock will occur. The locks are
164+
/// automatically released when the callback returns.
165+
///
166+
/// # Safety
167+
///
168+
/// - The raw handle passed to the callback must not be manually destroyed.
169+
///
170+
/// [`A::Adapter`]: hal::Api::Adapter
171+
#[cfg(wgpu_core)]
172+
pub unsafe fn as_hal<A: wgc::hal_api::HalApi, F: FnOnce(Option<&A::Adapter>) -> R, R>(
173+
&self,
174+
hal_adapter_callback: F,
175+
) -> R {
176+
if let Some(ctx) = self
177+
.context
178+
.as_any()
179+
.downcast_ref::<crate::backend::ContextWgpuCore>()
180+
{
181+
unsafe { ctx.adapter_as_hal::<A, F, R>(self.id.into(), hal_adapter_callback) }
182+
} else {
183+
hal_adapter_callback(None)
184+
}
185+
}
186+
187+
/// Returns whether this adapter may present to the passed surface.
188+
pub fn is_surface_supported(&self, surface: &Surface<'_>) -> bool {
189+
DynContext::adapter_is_surface_supported(
190+
&*self.context,
191+
&self.id,
192+
self.data.as_ref(),
193+
&surface.id,
194+
surface.surface_data.as_ref(),
195+
)
196+
}
197+
198+
/// The features which can be used to create devices on this adapter.
199+
pub fn features(&self) -> Features {
200+
DynContext::adapter_features(&*self.context, &self.id, self.data.as_ref())
201+
}
202+
203+
/// The best limits which can be used to create devices on this adapter.
204+
pub fn limits(&self) -> Limits {
205+
DynContext::adapter_limits(&*self.context, &self.id, self.data.as_ref())
206+
}
207+
208+
/// Get info about the adapter itself.
209+
pub fn get_info(&self) -> AdapterInfo {
210+
DynContext::adapter_get_info(&*self.context, &self.id, self.data.as_ref())
211+
}
212+
213+
/// Get info about the adapter itself.
214+
pub fn get_downlevel_capabilities(&self) -> DownlevelCapabilities {
215+
DynContext::adapter_downlevel_capabilities(&*self.context, &self.id, self.data.as_ref())
216+
}
217+
218+
/// Returns the features supported for a given texture format by this adapter.
219+
///
220+
/// Note that the WebGPU spec further restricts the available usages/features.
221+
/// To disable these restrictions on a device, request the [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] feature.
222+
pub fn get_texture_format_features(&self, format: TextureFormat) -> TextureFormatFeatures {
223+
DynContext::adapter_get_texture_format_features(
224+
&*self.context,
225+
&self.id,
226+
self.data.as_ref(),
227+
format,
228+
)
229+
}
230+
231+
/// Generates a timestamp using the clock used by the presentation engine.
232+
///
233+
/// When comparing completely opaque timestamp systems, we need a way of generating timestamps that signal
234+
/// the exact same time. You can do this by calling your own timestamp function immediately after a call to
235+
/// this function. This should result in timestamps that are 0.5 to 5 microseconds apart. There are locks
236+
/// that must be taken during the call, so don't call your function before.
237+
///
238+
/// ```no_run
239+
/// # let adapter: wgpu::Adapter = panic!();
240+
/// # let some_code = || wgpu::PresentationTimestamp::INVALID_TIMESTAMP;
241+
/// use std::time::{Duration, Instant};
242+
/// let presentation = adapter.get_presentation_timestamp();
243+
/// let instant = Instant::now();
244+
///
245+
/// // We can now turn a new presentation timestamp into an Instant.
246+
/// let some_pres_timestamp = some_code();
247+
/// let duration = Duration::from_nanos((some_pres_timestamp.0 - presentation.0) as u64);
248+
/// let new_instant: Instant = instant + duration;
249+
/// ```
250+
//
251+
/// [Instant]: std::time::Instant
252+
pub fn get_presentation_timestamp(&self) -> PresentationTimestamp {
253+
DynContext::adapter_get_presentation_timestamp(&*self.context, &self.id, self.data.as_ref())
254+
}
255+
}

0 commit comments

Comments
 (0)