Closed PoignardAzur closed 4 years ago
I think this could be handled with a GDNative library (or C++ module) that integrates with a WebAssembly runtime, so you could load such modules when desired.
That would be a good first step.
But I want to emphasize, a tight wasm integration could completely replace GDNative in the long term. There would be a transition cost, but the benefits (ocap sandboxing, better introspection, standardized API) would be superior to keeping it as a GDNative front-end.
@PoignardAzur What about performance? Many people use GDNative for performance-critical tasks.
I haven't looked into it too hard, but from what I remember, wasm is somewhere around 10% slower than native. I'd wager that it gets faster if you can disable bounds-checking and other safety features.
wasm would be really great for add-ons on the AssetLib, you'd get close to native performance but without the need of compilation or shipping multiple binaries.
Concerning WASI, this requires some thinking. WASI is an abstraction layer of the OS APIs, but so is Godot itself... So if you want to access let's say the microphone, WASI will surely have an API for that one day, but Godot already has that too.
It's not clear to me whereas WASI is necessarily used with wasm or if it can be used natively from compiled C++ ?
If you can call it from C++, then it would actually make sense for Godot itself to use WASI as a platform, on the long run it would save developer time because they wouldn't have to implement abstractions for all sensors and APIs over Mac, Win, Linux, IOS, Android, Web, etc... but it would be done by WASI for us.
Concerning GDNative, in any case it is important to keep the possibility to compile C++ / Rust / etc. natively. Currently wasm perf are still not the same as native (some plots here) also some people/studios might want to use special optimizations or some custom/proprietary/platform-specific libraries that are not accessible from wasm.
However, if WASI APIs can be called from C++ then GDNative could be transformed as a WASI Module (so one "Godot" box on that picture) and you would call those Godot WASI APIs from any language that can use WASI, whereas it is from native compiled code or from wasm.
In any case if I write a C++ / Rust / etc. add-on, it would be a shame that I have two different code bases, one that calls "GDNative APIs", one that calls "Godot wasm APIs".
This may be of interest too (not sure): https://hacks.mozilla.org/2019/08/webassembly-interface-types/
Edit: There's also this as of 2019-11-21: https://v8.dev/blog/emscripten-standalone-wasm
Interface types aren't nearly mature enough to be useful to Godot. On the other hand, someone with some experience with Godot's internals should probably take part in the standardization process on the Interface Types repository, to make sure the needs of a game engine like Godot are taken into account.
I just stumbled upon this issue, I think WebAssembly it's a great use case for plugins and scripts!
I work at Wasmer and I'd love to help an integration! (a few other projects are already using it for plugins!)
Let me know if you would like any help or assistance :)
@syrusakbary Most of the projects that I've seen that use C++ and WASM use a .dll for the runtime. I think Godot would probably prefer a statically linked runtime. It's probably best if it's compiled as part of Godot's normal build with SCONS.
However, since Wasmer is written in Rust, and would likely have cargo build the static lib (probably started by SCONS), the WASM plugin using version of Godot should probably be a compile time option. The Mono/C# using build is the same way, so there is precedent.
Closing in favor of https://github.com/godotengine/godot-proposals/issues/147, as we now track feature proposals on the Godot proposals repository.
FYI for anyone subscribed: "WASM Engine for Godot" (https://gitlab.com/RancidBacon/godot-wasm-engine) now enables support for executing WebAssembly from Godot.
More details on the previously linked proposal issue: https://github.com/godotengine/godot-proposals/issues/147#issuecomment-670349142
@syrusakbary The project currently uses Wasmtime but it's likely Wasmer support could be added for the right price. ;)
Good work on the integration!
I bet than when you want to maximize runtime speed Wasmer would come in handy 🤗
A plugin to enable plugins? That's a step in the right direction. We really need it intergrated with Godot to enable it on all supported platforms, and the API should make it not be used on html to enable use with the html wasm target's native runtime when exporting to the html target.
Ping for those subscribed. I've created a GDNative Godot Wasm addon that may address some of the functionality proposed here. Uses Wasmer as runtime.
Godot currently supports exporting to WebAssembly, and through GDNative, importing from C/C++ and other languages. But it doesn't support importing WebAssembly modules, which I think is a big omission.
WebAssembly is a good format to import for the same reason glTF is:
WebAssembly plugins would have a lot of advantages over GDNative, including:
Write Once, Run Anywhere: Right now, if I want to include C++ code in my Godot project, I need to compile it to a different shared library format for every platform I want to target; the process is under-documented, and I'm told it can hit snags when exporting to iOS. On the other hand, once you've compiled to WebAssembly, you're done. The code runs the same on every platform.
Fewer compatibility problems: This is particularly useful in development pipelines that include non-coders. I'm currently working on a game where a friend of mines makes the assets. I use Linux, he uses Windows. I set up my project with C++ scripts, but now he can't build the project unless he installs Visual C++ and builds the scripts on his side, which is complicated because I'm the one writing the build scripts. With wasm compatibility, I could just export a bunch of binaries on github, have him install them and he could work on assets with worrying about compiling the scripts.
Sandboxing and object capabilities: wasm is sandboxed by default. The upcoming WASI API will ship with object capabilities, which allow programs to executed untrusted code without compromising your filesystem, which would be especially useful for integrated modding systems. The current approach gives native scripts unrestricted access to the filesystem, and relies on the community to spot any malicious code published on the asset library. The event-stream incident has shown that this approach does not scale well, and that targeted attacks do happen once a platform is popular enough.
These would be the short-term benefits, that a good wasm implementation would provide. On the longer term, integrating wasm into Godot would leverage improvements from developers working on other parts of the ecosystem:
GDScript could be compiled to wasm. This would allow the engine to leverage wasm optimizers, instead of coming up with its own optimizations.
Godot could use source maps to debug native code in-editor.
Game developers could use wasm modules to import other languages' ecosystems that are missing in Godot. For instance, developers who want to use Python modules in GDScript could export these modules to wasm, and import the wasm code from Godot.
Now, WebAssembly as a standard isn't ready to be integrated in Godot yet. There are a few proposals (reference types, WebIDL bindings, WASI) that need to be standardized and implemented in compilers and runtimes before wasm can be integrated into Godot.
But I think it's worth starting to consider it now. I'm especially interested in what @Faless and @eska014 think on the subject. What kind of work is needed to integrate a wasm interpreter into Godot? Is it something that can plausibly be added to the 4.0 roadmap?