-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Get Bevy building for WebAssembly with multithreading #12205
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 <[email protected]>
Co-authored-by: Alice Cecile <[email protected]>
/// 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 <[email protected]>
.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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
@mockersf I got it fixed after a few attempts. I needed to add |
Is there another blocker to removing the |
There isn't, but |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
I believe removing fragile-send-sync-non-atomic-wasm
would indeed be better. This should remove a bunch of cfg
s 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should probably be noted that it will panic if dropped in another thread as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@daxpedda Good call out. I updated the comment.
Co-authored-by: daxpedda <[email protected]>
I think this PR also resolves #9304. Marking up the priority on this given the potential unsoundness implications. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
fragile-send-sync-non-atomic-wasm
doesn't do anything inwgpu
when theatomics
flag 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
atomics
flag is enabled. This does not yet multithread Bevy itself, but it allows Bevy users to use a crate likewasm_thread
to 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:
cpal
crashes immediately when theatomics
flag 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_thread
you need to enable thees_modules
feature.Solution
The largest obstacle to compiling Bevy with
atomics
on web is thatwgpu
types 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
wgpu
types in asend_wrapper::SendWrapper
that is Send / Sync, but panics if accessed off thewgpu
thread.Changelog
wgpu
types that are notSend
are wrapped insend_wrapper::SendWrapper
on Wasm + 'atomics'Questions