mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-21 14:23:32 +00:00
Add utils for WebGPU support detection & Instance creation (#6371)
* Utils for WebGPU support detection & Instance creation Clarifies the docs on `wgpu::Instance` accordingly * changelog entry * fix adapter check --------- Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>
This commit is contained in:
parent
fe7fbd4a4a
commit
59f56e0263
@ -89,6 +89,7 @@ By @bradwerth [#6216](https://github.com/gfx-rs/wgpu/pull/6216).
|
||||
#### General
|
||||
|
||||
- Add `VideoFrame` to `ExternalImageSource` enum. By @jprochazk in [#6170](https://github.com/gfx-rs/wgpu/pull/6170)
|
||||
- Add `wgpu::util::new_instance_with_webgpu_detection` & `wgpu::util::is_browser_webgpu_supported` to make it easier to support WebGPU & WebGL in the same binary. By @wumpf in [#6371](https://github.com/gfx-rs/wgpu/pull/6371)
|
||||
|
||||
#### Vulkan
|
||||
|
||||
|
@ -93,10 +93,15 @@ impl Instance {
|
||||
/// during instantiation, and which [DX12 shader compiler][Dx12Compiler] wgpu will use.
|
||||
///
|
||||
/// [`Backends::BROWSER_WEBGPU`] takes a special role:
|
||||
/// If it is set and WebGPU support is detected, this instance will *only* be able to create
|
||||
/// WebGPU adapters. If you instead want to force use of WebGL, either
|
||||
/// disable the `webgpu` compile-time feature or don't add the [`Backends::BROWSER_WEBGPU`]
|
||||
/// flag to the the `instance_desc`'s `backends` field.
|
||||
/// If it is set and a [`navigator.gpu`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/gpu)
|
||||
/// object is present, this instance will *only* be able to create WebGPU adapters.
|
||||
///
|
||||
/// ⚠️ On some browsers this check is insufficient to determine whether WebGPU is supported,
|
||||
/// as the browser may define the `navigator.gpu` object, but be unable to create any WebGPU adapters.
|
||||
/// For targeting _both_ WebGPU & WebGL is recommended to use [`crate::util::new_instance_with_webgpu_detection`].
|
||||
///
|
||||
/// If you instead want to force use of WebGL, either disable the `webgpu` compile-time feature
|
||||
/// or don't add the [`Backends::BROWSER_WEBGPU`] flag to the the `instance_desc`'s `backends` field.
|
||||
/// If it is set and WebGPU support is *not* detected, the instance will use wgpu-core
|
||||
/// to create adapters. Meaning that if the `webgl` feature is enabled, it is able to create
|
||||
/// a WebGL adapter.
|
||||
|
@ -1087,8 +1087,12 @@ pub struct BrowserGpuPropertyInaccessible;
|
||||
/// Returns the browser's gpu object or `Err(BrowserGpuPropertyInaccessible)` if
|
||||
/// the current context is neither the main thread nor a dedicated worker.
|
||||
///
|
||||
/// If WebGPU is not supported, the Gpu property is `undefined`, and so this
|
||||
/// function will return `Ok(None)`.
|
||||
/// If WebGPU is not supported, the Gpu property may (!) be `undefined`,
|
||||
/// and so this function will return `Ok(None)`.
|
||||
/// Note that this check is insufficient to determine whether WebGPU is
|
||||
/// supported, as the browser may define the Gpu property, but be unable to
|
||||
/// create any WebGPU adapters.
|
||||
/// To detect whether WebGPU is supported, use the [`crate::utils::is_browser_webgpu_supported`] function.
|
||||
///
|
||||
/// See:
|
||||
/// * <https://developer.mozilla.org/en-US/docs/Web/API/Navigator/gpu>
|
||||
|
@ -135,3 +135,61 @@ pub fn gles_minor_version_from_env() -> Option<wgt::Gles3MinorVersion> {
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Determines whether the [`Backends::BROWSER_WEBGPU`] backend is supported.
|
||||
///
|
||||
/// The result can only be true if this is called from the main thread or a dedicated worker.
|
||||
/// For convenience, this is also supported on non-wasm targets, always returning false there.
|
||||
pub async fn is_browser_webgpu_supported() -> bool {
|
||||
#[cfg(webgpu)]
|
||||
{
|
||||
// In theory it should be enough to check for the presence of the `gpu` property...
|
||||
let gpu = crate::backend::get_browser_gpu_property();
|
||||
let Ok(Some(gpu)) = gpu else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// ...but in practice, we also have to try to create an adapter, since as of writing
|
||||
// Chrome on Linux has the `gpu` property but doesn't support WebGPU.
|
||||
let adapter_promise = gpu.request_adapter();
|
||||
wasm_bindgen_futures::JsFuture::from(adapter_promise)
|
||||
.await
|
||||
.map_or(false, |adapter| {
|
||||
!adapter.is_undefined() && !adapter.is_null()
|
||||
})
|
||||
}
|
||||
#[cfg(not(webgpu))]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an new instance of wgpu, but disabling [`Backends::BROWSER_WEBGPU`] if no WebGPU support was detected.
|
||||
///
|
||||
/// If the instance descriptor enables [`Backends::BROWSER_WEBGPU`],
|
||||
/// this checks via [`is_browser_webgpu_supported`] for WebGPU support before forwarding
|
||||
/// the descriptor with or without [`Backends::BROWSER_WEBGPU`] respecitively to [`Instance::new`].
|
||||
///
|
||||
/// You should prefer this method over [`Instance::new`] if you want to target WebGPU and automatically
|
||||
/// fall back to WebGL if WebGPU is not available.
|
||||
/// This is because WebGPU support has to be decided upon instance creation and [`Instance::new`]
|
||||
/// (being a `sync` function) can't establish WebGPU support (details see [`is_browser_webgpu_supported`]).
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If no backend feature for the active target platform is enabled,
|
||||
/// this method will panic, see [`Instance::enabled_backend_features()`].
|
||||
#[allow(unused_mut)]
|
||||
pub async fn new_instance_with_webgpu_detection(
|
||||
mut instance_desc: wgt::InstanceDescriptor,
|
||||
) -> crate::Instance {
|
||||
if instance_desc
|
||||
.backends
|
||||
.contains(wgt::Backends::BROWSER_WEBGPU)
|
||||
&& !is_browser_webgpu_supported().await
|
||||
{
|
||||
instance_desc.backends.remove(wgt::Backends::BROWSER_WEBGPU);
|
||||
}
|
||||
|
||||
crate::Instance::new(instance_desc)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user