mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +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
|
#### General
|
||||||
|
|
||||||
- Add `VideoFrame` to `ExternalImageSource` enum. By @jprochazk in [#6170](https://github.com/gfx-rs/wgpu/pull/6170)
|
- 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
|
#### Vulkan
|
||||||
|
|
||||||
|
@ -93,10 +93,15 @@ impl Instance {
|
|||||||
/// during instantiation, and which [DX12 shader compiler][Dx12Compiler] wgpu will use.
|
/// during instantiation, and which [DX12 shader compiler][Dx12Compiler] wgpu will use.
|
||||||
///
|
///
|
||||||
/// [`Backends::BROWSER_WEBGPU`] takes a special role:
|
/// [`Backends::BROWSER_WEBGPU`] takes a special role:
|
||||||
/// If it is set and WebGPU support is detected, this instance will *only* be able to create
|
/// If it is set and a [`navigator.gpu`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/gpu)
|
||||||
/// WebGPU adapters. If you instead want to force use of WebGL, either
|
/// object is present, this instance will *only* be able to create WebGPU adapters.
|
||||||
/// disable the `webgpu` compile-time feature or don't add the [`Backends::BROWSER_WEBGPU`]
|
///
|
||||||
/// flag to the the `instance_desc`'s `backends` field.
|
/// ⚠️ 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
|
/// 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
|
/// to create adapters. Meaning that if the `webgl` feature is enabled, it is able to create
|
||||||
/// a WebGL adapter.
|
/// a WebGL adapter.
|
||||||
|
@ -1087,8 +1087,12 @@ pub struct BrowserGpuPropertyInaccessible;
|
|||||||
/// Returns the browser's gpu object or `Err(BrowserGpuPropertyInaccessible)` if
|
/// Returns the browser's gpu object or `Err(BrowserGpuPropertyInaccessible)` if
|
||||||
/// the current context is neither the main thread nor a dedicated worker.
|
/// 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
|
/// If WebGPU is not supported, the Gpu property may (!) be `undefined`,
|
||||||
/// function will return `Ok(None)`.
|
/// 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:
|
/// See:
|
||||||
/// * <https://developer.mozilla.org/en-US/docs/Web/API/Navigator/gpu>
|
/// * <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