Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow WebGPU & WebGL in same wasm and detect WebGPU availability #5044

Merged
merged 14 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ jobs:
- name: execute tests
run: |
cd wgpu
wasm-pack test --headless --chrome --features webgl --workspace
wasm-pack test --headless --chrome --no-default-features --features wgsl,webgl --workspace

gpu-test:
# runtime is normally 5-15 minutes
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ Conversion to `wgpu::SurfaceTarget` is automatic for anything implementing `raw-
meaning that you can continue to e.g. pass references to winit windows as before.
By @wumpf in [#4984](https://github.com/gfx-rs/wgpu/pull/4984)

### WebGPU & WebGL in the same binary

Enabling `webgl` no longer removes the `webgpu` backend.
Instead, there's a new (default enabled) `webgpu` feature that allows to explicitly opt-out of `webgpu` if so desired.
If both `webgl` & `webgpu` are enabled, `wgpu::Instance` decides upon creation whether to target wgpu-core/WebGL or WebGPU.
This means that adapter selection is not handled as with regular adapters, but still allows to decide at runtime whether
`webgpu` or the `webgl` backend should be used using a single wasm binary.
By @wumpf in [#5044](https://github.com/gfx-rs/wgpu/pull/5044)

### New Features

#### General
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ To run the test suite on WebGL (currently incomplete):

```
cd wgpu
wasm-pack test --headless --chrome --features webgl --workspace
wasm-pack test --headless --chrome --no-default-features --features webgl --workspace
```

This will automatically run the tests using a packaged browser. Remove `--headless` to run the tests with whatever browser you wish at `http://localhost:8000`.
Expand Down
12 changes: 11 additions & 1 deletion tests/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ pub fn initialize_instance() -> Instance {
//
// We can potentially work support back into the test runner in the future, but as the adapters are matched up
// based on adapter index, removing some backends messes up the indexes in annoying ways.
let backends = Backends::all();
//
// WORKAROUND for https://github.com/rust-lang/cargo/issues/7160:
// `--no-default-features` is not passed through correctly to the test runner.
// We use it whenever we want to explicitly run with webgl instead of webgpu.
// To "disable" webgpu regardless, we do this by removing the webgpu backend whenever we see
// the webgl feature.
let backends = if cfg!(feature = "webgl") {
Backends::all() - Backends::BROWSER_WEBGPU
} else {
Backends::all()
};
let dx12_shader_compiler = wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default();
let gles_minor_version = wgpu::util::gles_minor_version_from_env().unwrap_or_default();
Instance::new(wgpu::InstanceDescriptor {
Expand Down
4 changes: 2 additions & 2 deletions tests/tests/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ fn device_lifetime_check() {

instance.poll_all(false);

let pre_report = instance.generate_report();
let pre_report = instance.generate_report().unwrap().unwrap();

drop(queue);
drop(device);
let post_report = instance.generate_report();
let post_report = instance.generate_report().unwrap().unwrap();
assert_ne!(
pre_report, post_report,
"Queue and Device has not been dropped as expected"
Expand Down
32 changes: 16 additions & 16 deletions tests/tests/mem_leaks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async fn draw_test_with_reports(

use wgpu::util::DeviceExt;

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.devices.num_allocated, 1);
assert_eq!(report.queues.num_allocated, 1);
Expand All @@ -21,7 +21,7 @@ async fn draw_test_with_reports(
.device
.create_shader_module(wgpu::include_wgsl!("./vertex_indices/draw.vert.wgsl"));

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.shader_modules.num_allocated, 1);

Expand All @@ -41,7 +41,7 @@ async fn draw_test_with_reports(
}],
});

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.buffers.num_allocated, 0);
assert_eq!(report.bind_groups.num_allocated, 0);
Expand All @@ -54,7 +54,7 @@ async fn draw_test_with_reports(
mapped_at_creation: false,
});

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.buffers.num_allocated, 1);

Expand All @@ -67,7 +67,7 @@ async fn draw_test_with_reports(
}],
});

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.buffers.num_allocated, 1);
assert_eq!(report.bind_groups.num_allocated, 1);
Expand All @@ -81,7 +81,7 @@ async fn draw_test_with_reports(
push_constant_ranges: &[],
});

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.buffers.num_allocated, 1);
assert_eq!(report.pipeline_layouts.num_allocated, 1);
Expand Down Expand Up @@ -113,7 +113,7 @@ async fn draw_test_with_reports(
multiview: None,
});

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.buffers.num_allocated, 1);
assert_eq!(report.bind_groups.num_allocated, 1);
Expand All @@ -125,7 +125,7 @@ async fn draw_test_with_reports(

drop(shader);

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.shader_modules.num_allocated, 1);
assert_eq!(report.shader_modules.num_kept_from_user, 0);
Expand Down Expand Up @@ -153,15 +153,15 @@ async fn draw_test_with_reports(
);
let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.buffers.num_allocated, 1);
assert_eq!(report.texture_views.num_allocated, 1);
assert_eq!(report.textures.num_allocated, 1);

drop(texture);

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.buffers.num_allocated, 1);
assert_eq!(report.texture_views.num_allocated, 1);
Expand All @@ -173,7 +173,7 @@ async fn draw_test_with_reports(
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.command_buffers.num_allocated, 1);
assert_eq!(report.buffers.num_allocated, 1);
Expand All @@ -193,7 +193,7 @@ async fn draw_test_with_reports(
rpass.set_pipeline(&pipeline);
rpass.set_bind_group(0, &bg, &[]);

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.buffers.num_allocated, 1);
assert_eq!(report.bind_groups.num_allocated, 1);
Expand All @@ -216,7 +216,7 @@ async fn draw_test_with_reports(
drop(bg);
drop(buffer);

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.command_buffers.num_kept_from_user, 1);
assert_eq!(report.render_pipelines.num_kept_from_user, 0);
Expand All @@ -237,15 +237,15 @@ async fn draw_test_with_reports(

let submit_index = ctx.queue.submit(Some(encoder.finish()));

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);
assert_eq!(report.command_buffers.num_allocated, 0);

ctx.async_poll(wgpu::Maintain::wait_for(submit_index))
.await
.panic_on_timeout();

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);

assert_eq!(report.render_pipelines.num_allocated, 0);
Expand All @@ -260,7 +260,7 @@ async fn draw_test_with_reports(
drop(ctx.device);
drop(ctx.adapter);

let global_report = ctx.instance.generate_report();
let global_report = ctx.instance.generate_report().unwrap();
let report = global_report.hub_report(ctx.adapter_info.backend);

assert_eq!(report.queues.num_kept_from_user, 0);
Expand Down
7 changes: 6 additions & 1 deletion wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,12 @@ bitflags::bitflags! {
const METAL = 1 << Backend::Metal as u32;
/// Supported on Windows 10
const DX12 = 1 << Backend::Dx12 as u32;
/// Supported when targeting the web through webassembly
/// Supported when targeting the web through webassembly with the `webgpu` feature enabled.
///
/// The WebGPU backend is special in several ways:
/// It is not not implemented by `wgpu_core` and instead by the higher level `wgpu` crate.
/// Whether WebGPU is targeted is decided upon the creation of the `wgpu::Instance`,
/// *not* upon adapter creation. See `wgpu::Instance::new`.
const BROWSER_WEBGPU = 1 << Backend::BrowserWebGpu as u32;
/// All the apis that wgpu offers first tier of support for.
///
Expand Down
6 changes: 4 additions & 2 deletions wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ targets = [
[lib]

[features]
default = ["wgsl", "dx12", "metal"]
default = ["wgsl", "dx12", "metal", "webgpu"]

#! ### Backends
# --------------------------------------------------------------------
Expand All @@ -44,10 +44,12 @@ angle = ["wgc?/gles"]
## Enables the Vulkan backend on macOS & iOS.
vulkan-portability = ["wgc?/vulkan"]

## Enables the WebGPU backend on Wasm. Disabled when targeting `emscripten`.
webgpu = []

## Enables the GLES backend on Wasm
##
## * ⚠️ WIP: Currently will also enable GLES dependencies on any other targets.
## * ⚠️ WIP: This automatically disables use of WebGPU. See [#2804](https://github.com/gfx-rs/wgpu/issues/3514).
webgl = ["hal", "wgc/gles"]

#! ### Shading language support
Expand Down
3 changes: 2 additions & 1 deletion wgpu/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ fn main() {
cfg_aliases::cfg_aliases! {
native: { not(target_arch = "wasm32") },
webgl: { all(target_arch = "wasm32", not(target_os = "emscripten"), feature = "webgl") },
webgpu: { all(target_arch = "wasm32", not(target_os = "emscripten"), not(feature = "webgl")) },
webgpu: { all(target_arch = "wasm32", not(target_os = "emscripten"), feature = "webgpu") },
Emscripten: { all(target_arch = "wasm32", target_os = "emscripten") },
wgpu_core: { any(native, webgl, emscripten) },
send_sync: { any(
not(target_arch = "wasm32"),
all(feature = "fragile-send-sync-non-atomic-wasm", not(target_feature = "atomics"))
Expand Down
12 changes: 6 additions & 6 deletions wgpu/src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#[cfg(webgpu)]
mod web;
mod webgpu;
#[cfg(webgpu)]
pub(crate) use web::Context;
pub(crate) use webgpu::{get_browser_gpu_property, ContextWebGpu};

#[cfg(not(webgpu))]
mod direct;
#[cfg(not(webgpu))]
pub(crate) use direct::Context;
#[cfg(wgpu_core)]
mod wgpu_core;
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(wgpu_core)]
pub(crate) use wgpu_core::ContextWgpuCore;
Loading