Changed enumerate_adapters to be able to work with custom backends (#8230)

Co-authored-by: Andreas Reich <r_andreas2@web.de>
This commit is contained in:
Robin Cramer 2025-10-06 15:27:23 -04:00 committed by GitHub
parent 1072b87894
commit 4652ea4189
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 86 additions and 33 deletions

View File

@ -40,6 +40,20 @@ Bottom level categories:
## Unreleased
#### 'wgpu::Instance::enumerate_adapters` is now `async` & available on WebGPU
Making `enumerate_adapters` async allows custom backends to use it along with elimnating some native/non-native distinctions
This is a breaking change
```diff
- pub fn enumerate_adapters(&self, backends: Backends) -> Vec<Adapter> {
+ pub fn enumerate_adapters(&self, backends: Backends) -> impl Future<Output = Vec<Adapter>> {
```
By @R-Cramer4 in [#8230](https://github.com/gfx-rs/wgpu/pull/8230)
## v27.0.2 (2025-10-03)
### Bug Fixes
@ -175,7 +189,6 @@ by if the `Feature::MULTI_DRAW_INDIRECT_COUNT` feature is available on the devic
By @cwfitzgerald in [#8162](https://github.com/gfx-rs/wgpu/pull/8162).
#### `wgpu::PollType::Wait` has now an optional timeout
We removed `wgpu::PollType::WaitForSubmissionIndex` and added fields to `wgpu::PollType::Wait` in order to express timeouts.

13
Cargo.lock generated
View File

@ -120,9 +120,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
version = "0.6.20"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse",
@ -600,9 +600,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.39"
version = "1.2.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f"
checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb"
dependencies = [
"find-msvc-tools",
"jobserver",
@ -1438,9 +1438,9 @@ dependencies = [
[[package]]
name = "find-msvc-tools"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3"
[[package]]
name = "fixedbitset"
@ -5012,6 +5012,7 @@ dependencies = [
"env_logger",
"hashbrown 0.16.0",
"pico-args",
"pollster",
"serde",
"serde_json",
"wgpu",

View File

@ -203,7 +203,7 @@ pub(crate) async fn get_adapter_with_capabilities_or_from_env(
);
adapter
} else {
let adapters = instance.enumerate_adapters(Backends::all());
let adapters = instance.enumerate_adapters(Backends::all()).await;
let mut chosen_adapter = None;
for adapter in adapters {

View File

@ -55,6 +55,13 @@ impl InstanceInterface for CustomInstance {
fn wgsl_language_features(&self) -> wgpu::WgslLanguageFeatures {
unimplemented!()
}
fn enumerate_adapters(
&self,
_backends: wgpu::Backends,
) -> Pin<Box<dyn wgpu::custom::EnumerateAdapterFuture>> {
unimplemented!()
}
}
#[derive(Debug)]

View File

@ -122,7 +122,7 @@ pub async fn initialize_adapter(
cfg_if::cfg_if! {
if #[cfg(not(target_arch = "wasm32"))] {
let adapter_iter = instance.enumerate_adapters(backends);
let adapter_iter = instance.enumerate_adapters(backends).await;
let adapter = adapter_iter.into_iter()
// If we have a report, we only want to match the adapter with the same info.
//
@ -136,7 +136,7 @@ pub async fn initialize_adapter(
panic!(
"Could not find adapter with info {:#?} in {:#?}",
adapter_report.map(|r| &r.info),
instance.enumerate_adapters(backends).into_iter().map(|a| a.get_info()).collect::<Vec<_>>(),
instance.enumerate_adapters(backends).await.into_iter().map(|a| a.get_info()).collect::<Vec<_>>(),
);
};
} else {

View File

@ -16,6 +16,7 @@ bitflags.workspace = true
env_logger.workspace = true
hashbrown = { workspace = true, features = ["serde"] }
pico-args.workspace = true
pollster.workspace = true
serde = { workspace = true, features = ["default"] }
serde_json.workspace = true
wgpu.workspace = true

View File

@ -25,7 +25,8 @@ impl GpuReport {
desc.flags = wgpu::InstanceFlags::debugging();
desc.with_env()
});
let adapters = instance.enumerate_adapters(wgpu::Backends::all());
let adapters = pollster::block_on(instance.enumerate_adapters(wgpu::Backends::all()));
let mut devices = Vec::with_capacity(adapters.len());
for adapter in adapters {

View File

@ -1,4 +1,3 @@
#[cfg(wgpu_core)]
use alloc::vec::Vec;
use core::future::Future;
@ -142,23 +141,18 @@ impl Instance {
/// # Arguments
///
/// - `backends` - Backends from which to enumerate adapters.
#[cfg(wgpu_core)]
pub fn enumerate_adapters(&self, backends: Backends) -> Vec<Adapter> {
let Some(core_instance) = self.inner.as_core_opt() else {
return Vec::new();
};
pub fn enumerate_adapters(&self, backends: Backends) -> impl Future<Output = Vec<Adapter>> {
let future = self.inner.enumerate_adapters(backends);
core_instance
.enumerate_adapters(backends)
.into_iter()
.map(|adapter| {
let core = backend::wgpu_core::CoreAdapter {
context: core_instance.clone(),
id: adapter,
};
crate::Adapter { inner: core.into() }
})
.collect()
async move {
future
.await
.iter()
.map(|adapter| Adapter {
inner: adapter.clone(),
})
.collect()
}
}
/// Retrieves an [`Adapter`] which matches the given [`RequestAdapterOptions`].

View File

@ -1569,6 +1569,20 @@ impl dispatch::InstanceInterface for ContextWebGpu {
))))
}
}
fn enumerate_adapters(
&self,
_backends: crate::Backends,
) -> Pin<Box<dyn dispatch::EnumerateAdapterFuture>> {
let future = self.request_adapter(&crate::RequestAdapterOptions::default());
let enumerate_future = async move {
let adapter = future.await;
match adapter {
Ok(a) => vec![a],
Err(_) => vec![],
}
};
Box::pin(enumerate_future)
}
fn poll_all_devices(&self, _force_wait: bool) -> bool {
// Devices are automatically polled.

View File

@ -28,7 +28,6 @@ use wgt::{
WasmNotSendSync,
};
use crate::util::Mutex;
use crate::{
api,
dispatch::{self, BlasCompactCallback, BufferMappedRangeInterface},
@ -36,6 +35,7 @@ use crate::{
CompilationMessageType, ErrorSource, Features, Label, LoadOp, MapMode, Operations,
ShaderSource, SurfaceTargetUnsafe, TextureDescriptor, Tlas,
};
use crate::{dispatch::DispatchAdapter, util::Mutex};
#[derive(Clone)]
pub struct ContextWgpuCore(Arc<wgc::global::Global>);
@ -902,6 +902,24 @@ impl dispatch::InstanceInterface for ContextWgpuCore {
},
)
}
fn enumerate_adapters(
&self,
backends: crate::Backends,
) -> Pin<Box<dyn dispatch::EnumerateAdapterFuture>> {
let adapters: Vec<DispatchAdapter> = self
.enumerate_adapters(backends)
.into_iter()
.map(|adapter| {
let core = crate::backend::wgpu_core::CoreAdapter {
context: self.clone(),
id: adapter,
};
core.into()
})
.collect();
Box::pin(ready(adapters))
}
}
impl dispatch::AdapterInterface for CoreAdapter {

View File

@ -39,6 +39,7 @@ trait_alias!(RequestAdapterFuture: Future<Output = Result<DispatchAdapter, wgt::
trait_alias!(RequestDeviceFuture: Future<Output = Result<(DispatchDevice, DispatchQueue), crate::RequestDeviceError>> + WasmNotSend + 'static);
trait_alias!(PopErrorScopeFuture: Future<Output = Option<crate::Error>> + WasmNotSend + 'static);
trait_alias!(ShaderCompilationInfoFuture: Future<Output = crate::CompilationInfo> + WasmNotSend + 'static);
trait_alias!(EnumerateAdapterFuture: Future<Output = Vec<DispatchAdapter>> + WasmNotSend + 'static);
// We can't use trait aliases here, as you can't convert from a dyn Trait to dyn Supertrait _yet_.
#[cfg(send_sync)]
@ -93,6 +94,9 @@ pub trait InstanceInterface: CommonTraits {
#[cfg(feature = "wgsl")]
fn wgsl_language_features(&self) -> crate::WgslLanguageFeatures;
fn enumerate_adapters(&self, backends: crate::Backends)
-> Pin<Box<dyn EnumerateAdapterFuture>>;
}
pub trait AdapterInterface: CommonTraits {

View File

@ -6,7 +6,7 @@ use crate::Backends;
/// Initialize the adapter obeying the `WGPU_ADAPTER_NAME` environment variable.
#[cfg(wgpu_core)]
#[cfg_attr(not(std), expect(unused_variables, unreachable_code))]
pub fn initialize_adapter_from_env(
pub async fn initialize_adapter_from_env(
instance: &Instance,
compatible_surface: Option<&Surface<'_>>,
) -> Result<Adapter, wgt::RequestAdapterError> {
@ -23,7 +23,7 @@ pub fn initialize_adapter_from_env(
}
};
let adapters = instance.enumerate_adapters(crate::Backends::all());
let adapters = instance.enumerate_adapters(crate::Backends::all()).await;
let mut chosen_adapter = None;
for adapter in adapters {
@ -46,7 +46,7 @@ pub fn initialize_adapter_from_env(
/// Initialize the adapter obeying the `WGPU_ADAPTER_NAME` environment variable.
#[cfg(not(wgpu_core))]
pub fn initialize_adapter_from_env(
pub async fn initialize_adapter_from_env(
_instance: &Instance,
_compatible_surface: Option<&Surface<'_>>,
) -> Result<Adapter, wgt::RequestAdapterError> {
@ -58,7 +58,7 @@ pub async fn initialize_adapter_from_env_or_default(
instance: &Instance,
compatible_surface: Option<&Surface<'_>>,
) -> Result<Adapter, wgt::RequestAdapterError> {
match initialize_adapter_from_env(instance, compatible_surface) {
match initialize_adapter_from_env(instance, compatible_surface).await {
Ok(a) => Ok(a),
Err(_) => {
instance