Get Bevy building for WebAssembly with multithreading#12205
Get Bevy building for WebAssembly with multithreading#12205alice-i-cecile merged 18 commits intobevyengine:mainfrom
Conversation
Same PR please :) It would be nice to be able to use that check to ensure that this PR is green. |
* Move a comment * Run CI on nightly
|
would you need to disable this feature to check that wgpu works correctly there? bevy/crates/bevy_render/Cargo.toml Line 75 in 599e5e4 |
|
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
| /// On other platforms the wrapper simply contains the wrapped value. | ||
| #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))] | ||
| #[derive(Debug, Clone)] | ||
| pub struct WgpuWrapper<T>(T); |
There was a problem hiding this comment.
It'd be ideal if this doesn't need to be public, as it's sort of an implementation detail. Perhaps we should make a wrapper for Surface since it's the only type used outside of bevy_render that needs this explicitly.
There was a problem hiding this comment.
@james7132 I'd also prefer it to be non-public, but the RenderQueue, RenderAdapter, RenderInstance, and RenderAdapterInfo structs all publicly expose their inner wgpu struct which needs to be wrapped in WgpuWrapper.
There was a problem hiding this comment.
OK sounds good to me. I believe @robtfm recently found that we may not need these wrappers anymore, but we can tackle that in a separate PR.
james7132
left a comment
There was a problem hiding this comment.
Overall I'm OK with this change. I'm glad we're starting to peak into enabling actual paralellism on the web.
With that said, I'm getting very concerned with how much cfg(target_arch = "wasm32"...) we're seeing across the engine. Much of this is teething pains for wasm support in Rust, which is understandable, particularly as it's the job of the engine to handle platform abstraction. However, problems arise when that platform abstraction itself is leaky, and plugins in the ecosystem and end users end up needing to deal with it, as evidenced by the endless stream of issues coming in. These problems are endemic of a deeper problem that needs to be addressed in the foundational crates for wasm support (i.e. wasm-bindgen), as the problems raised are seemingly viral.
| /// On other platforms the wrapper simply contains the wrapped value. | ||
| #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))] | ||
| #[derive(Debug, Clone)] | ||
| pub struct WgpuWrapper<T>(T); |
There was a problem hiding this comment.
OK sounds good to me. I believe @robtfm recently found that we may not need these wrappers anymore, but we can tackle that in a separate PR.
Co-authored-by: daxpedda <daxpedda@gmail.com>
.github/workflows/ci.yml
Outdated
| - uses: dtolnay/rust-toolchain@master | ||
| with: | ||
| toolchain: ${{ env.NIGHTLY_TOOLCHAIN }} | ||
| target: wasm32-unknown-unknown |
There was a problem hiding this comment.
| target: wasm32-unknown-unknown | |
| targets: wasm32-unknown-unknown,x86_64-unknown-linux-gnu |
CI is failing because it also needs this target
There was a problem hiding this comment.
That wasn't the issue, CI is still complaining:
"/home/runner/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/Cargo.lock" does not exist, unable to build with the standard library, try:
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
Co-authored-by: François <francois.mockers@vleue.com>
@mockersf I got it fixed after a few attempts. I needed to add |
|
Is there another blocker to removing the |
There isn't, but |
daxpedda
left a comment
There was a problem hiding this comment.
LGTM.
I believe removing fragile-send-sync-non-atomic-wasm would indeed be better. This should remove a bunch of cfgs as types would be more consistent between feature = "atomics" and not(feature = "atomics").
| /// On web with atomics enabled the inner value can only be accessed on the | ||
| /// `wgpu` thread or else a panic will occur. |
There was a problem hiding this comment.
It should probably be noted that it will panic if dropped in another thread as well.
There was a problem hiding this comment.
@daxpedda Good call out. I updated the comment.
Co-authored-by: daxpedda <daxpedda@gmail.com>
|
I think this PR also resolves #9304. Marking up the priority on this given the potential unsoundness implications. |
joseph-gio
left a comment
There was a problem hiding this comment.
LGTM
fragile-send-sync-non-atomic-wasmdoesn't do anything inwgpuwhen theatomicsflag is enabled, so there's no reason to bother enabling or disabling it.
Can you at least update the comments in the Cargo.toml? Currently it says this which no longer captures the whole picture
# `fragile-send-sync-non-atomic-wasm` feature means we can't use WASM threads for rendering
# It is enabled for now to avoid having to do a significant overhaul of the renderer just for wasm
Done! |
|
Thank you to everyone involved with the authoring or reviewing of this PR! This work is relatively important and needs release notes! Head over to bevyengine/bevy-website#1289 if you'd like to help out. |
Objective
This gets Bevy building on Wasm when the
atomicsflag is enabled. This does not yet multithread Bevy itself, but it allows Bevy users to use a crate likewasm_threadto spawn their own threads and manually parallelize work. This is a first step towards resolving #4078 . Also fixes #9304.This provides a foothold so that Bevy contributors can begin to think about multithreaded Wasm's constraints and Bevy can work towards changes to get the engine itself multithreaded.
Some flags need to be set on the Rust compiler when compiling for Wasm multithreading. Here's what my build script looks like, with the correct flags set, to test out Bevy examples on web:
A few notes:
cpalcrashes immediately when theatomicsflag is set. That is patched in Fix crash on Web / Wasm when 'atomics' flag is enabled RustAudio/cpal#837, but not yet in the latest crates.io release.That can be temporarily worked around by patching Cpal like so:
wasm_threadyou need to enable thees_modulesfeature.Solution
The largest obstacle to compiling Bevy with
atomicson web is thatwgputypes are not Send and Sync. Longer term Bevy will need an approach to handle that, but in the near term Bevy is already configured to be single-threaded on web.Therefor it is enough to wrap
wgputypes in asend_wrapper::SendWrapperthat is Send / Sync, but panics if accessed off thewgputhread.Changelog
wgputypes that are notSendare wrapped insend_wrapper::SendWrapperon Wasm + 'atomics'Questions