Open necrashter opened 1 year ago
Thanks for the detailed writeup! Threading on the web is a niche feature, and as stated in the issue, unsupported yet by the upstream Godot engine. There is also a good chance that the issue presented here has its root causes in emscripten
or the Rust standard library, both highly complex projects. As such, we'll mostly have to rely on motivated contributors for a possible solution to the problem.
Some potential starting points are:
std
internal __FastLocalKeyInner
unavailable on the wasm32-unknown-emscripten
target, and whether it can be fixed.thread::spawn
(presumably) is trying to call.If you're interested in helping out, please let us know in this issue, or reach out to us on Discord.
Background
Although Godot documentation says that multi-threading is not supported with GDNative, progress has been made since then. In particular, tracking issue for dynamic linking + pthreads has been closed in Emscripten repository because:
Therefore, we should be able to use multi-threading on web, even if it's limited.
Instructions
This section will describe how I built a GDNative Rust library with threads for web. It can serve as a starting point for those who want to work on this.
First, make sure that you can build your library without threads using the instructions in the book.
Compile the Godot web export template with both
threads_enabled=yes
andgdnative_enabled=yes
:Update
.cargo/config.toml
:Other flags you may try:
"-Ctarget-feature=+atomics,+bulk-memory,+mutable-globals"
,"-Clink-arg=-sWASM_WORKERS"
.The standard library must be recompiled with these flags as well. To do this, add
-Z build-std=panic_abort,std
to your build command:NOTE: Multi-threaded web apps depend on
SharedArrayBuffer
, which is only available if the webpage is cross-origin isolated. Here is a Python script (python3 -m http.server
replacement) for serving a cross-origin isolated webpages. Use it to test your exported game.Problems
Following the instructions above leads to the following compile error (tested on 2023-01-31):
The same error is repeated for all usages of
thread_local!
macro inparking_lot
.In order to quickly check whether it works without
thread_local
, I removed theparking_lot
dependency and one other usage ofthread_local!
ingdnative-core/src/export/emplace.rs
. I don't share the changes I made because it was quite hacky and ugly. For example, there's notry_lock_for(duration)
method for mutexes in standard library. So I replaced them withlock()
.With these changes, compile succeeds, and the library works correctly until a new thread is spawned. Spawning a new thread causes the following runtime error:
Thanks to chitoyuu for helping on Discord.
We haven't confirmed whether multi-threaded C/C++ GDNative build works on web yet. I failed to compile the simple tutorial plugin provided in official Godot docs for the web, let alone a multi-threaded one.