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

Add WASM (WASI) host support (including, but not limited to, the HTML5 target) #147

Open
Type1J opened this issue Oct 11, 2019 · 39 comments

Comments

@Type1J
Copy link

Type1J commented Oct 11, 2019

Describe the project you are working on:
I am working on an app that needs updates often due to new features.

Describe the problem or limitation you are having in your project:
Replacing a GDNative dll is how we currently need to distribute new updates. Each platform needs it's own dll. The dlls are written in Rust. GDScript isn't an option due to the CPU intensive tasks in other threads that we are performing.

Describe how this feature / enhancement will help you overcome this problem or limitation:
Only 1 .dll (.wasm) file will need to be produced, and it will work on all platforms

Show a mock up screenshots/video or a flow diagram explaining how your proposal will work:

Current:
Windows -> .dll
Linux -> .so
macOS -> .dylib
HTML5 -> Currently not supported, but desired
Android -> .so
iOS -> Currently not supported, but desired (for our project)

After proposal:
Windows, Linux, macOS, HTML5, Android, and iOS (potentially more) -> .wasm

Describe implementation detail for your proposal (in code), if possible:
The .wasm dynamic library would basically implement the same API as GDNative dynamic libraries currently do. See wasmer and WASI (https://wasi.dev/) for an example host native application.

If this enhancement will not be used often, can it be worked around with a few lines of script?:
No. Currently, this is a build system and distribution problem. The feature is the only option for a GDNative library for HTML5, and it can be used to prevent the need for other proposals to go into the core.

Is there a reason why this should be core and not an add-on in the asset library?:
It enables asset libraries to make "native"-ish extensions that can be used on multiple platforms. They may not be as fast as true native, but they are faster than GDScript by far, and enable legacy code in the same way that GDNative does, but WASI also provides sandboxing support that GDNative does not have, which reduces the security audit required in some cases with asset library GDNative dynamic libraries.

Bugsquad edit (keywords for easier searching): WebAssembly

@Calinou
Copy link
Member

Calinou commented Oct 11, 2019

See also godotengine/godot#28303.

@Frontrider
Copy link

You could try using this:
https://wasmtime.dev/
This is a standalone webassembly vm, with a lot of embedding options including C, WASI included.

This one also means that Godot would supports a huge number of languages without any specific runtimes. Debugging is a real question tough, as I don't know if webassembly has any way to map the bytecode back to whatever it was compiled from.

@robbiespeed
Copy link

As a stepping stone why not keep the existing structure of compiled per platform libraries, but add wasm to the list for the web platform. Later it could be tested weather allowing wasm to be used for all platform builds via some wasm runtime should be added as an option, by testing the performance impact that would introduce.

@Type1J
Copy link
Author

Type1J commented May 30, 2020

We are already using a Rust GDNative plugin that includes wasmer-runtime and loads a .wasm library that is switched out. We still don't support HTML5, but we've worked around this issue for now. I believe that it should be resolved before we expand to HTML5 and iOS.

@Frontrider
Copy link

@robbiespeed Things that are designed for the web are always fast. That's one of the main business targets. Faster execution means that your customer gets to your products sooner. Overly optimized javascript is not that much slower than native code (the parsing is the part where it has a small slowdown, yes I was surprised), and webassembly is even faster than that.
https://takahirox.github.io/WebAssembly-benchmark/

@robbiespeed
Copy link

@Frontrider yes wasm is faster than javascript (in some workloads), and we have come a long way in performance on the web, but it is still slower than native compiled code.

Here's a fairly in depth paper on wasm vs native performance https://arxiv.org/pdf/1901.09056.pdf

In that paper it describes that on average in their tests wasm performed roughly 1.5x slower than native.

@Frontrider
Copy link

Frontrider commented Jun 11, 2020

@robbiespeed I know that it's slower. Nothing is faster than native at this point. I personally don't think speed is going to be an issue for now (it's already faster than whatever runtime this small-ish team could produce on their own), and the plan is to compile gdscript to webassembly and that would be a big speedup on it's own. (I'm personally fond of gdscript, even tough I do not like python's syntax)
The benefits of not needing to write any specific compatibility layers for a large chunk of languages/tools is also big one.

And yes I agree, GDnative should remain and be improved, because there is a clear usecase for it.

@Calinou
Copy link
Member

Calinou commented Jun 11, 2020

and the plan is to compile gdscript to webassembly and that would be a big speedup on it's own.

I don't think that's currently planned.

@robbiespeed
Copy link

@Frontrider this proposal if I interpreted it correctly is about introducing wasm as a build target for gdnative projects, and replacing existing gdnative generated platform specific libraries with wasm, so that you only need to have one build target.

I am very much looking forward to the first part, because we need that in order to have web as a supported build target for gdnative projects. I don't think the second part is a good idea though unless it were optional, even then I don't see much benifit.

@TheRawMeatball
Copy link

This seems like the place where HTML5 support for gdnative is tracked, is this feature (primarily the first part) on the roadmap?

@Calinou
Copy link
Member

Calinou commented Jul 1, 2020

@TheRawMeatball Support for GDNative in HTML5 may happen in the future, but there's no target version.

@follower
Copy link

follower commented Aug 7, 2020

A way to call WebAssembly functions from Godot desktop apps today

I started on a project last year to integrate the Wasmtime WebAssembly runtime with Godot for desktop (Linux, Mac & Windows).

Over past couple of days I finally did a public release of the project "WASM Engine for Godot" (MIT License) in its current WIP stage if you're interested in checking it out: https://gitlab.com/RancidBacon/godot-wasm-engine

Current implementation details

The add-on is implemented on top of Foreigner--a wrapper for the libffi Foreign Function Interface library--along with some additions for buffer/struct support. (And is in part a demonstration of why I think FFI/ctypes-style support in the core would enable more functionality to be added (& added more easily) to Godot.)

The use of Foreigner means that the libwasmtime wrapper is written entirely in GDScript and further functionality from Wasmtime can be exposed without writing or compiling any C/C++: https://gitlab.com/RancidBacon/godot-wasm-engine/-/blob/main/src/addons/wasm-engine/WasmEngine.gd

The current wrapper was handwritten (in part because I was still figuring out how to embed libwasmtime as the C API was pretty under-documented when I started) but after gaining further experience with wrapping another complex library I'd probably look at doing more scripted generation of the binding moving forward.

Demonstration projects

There are two demonstration projects built on Godot which have binaries available for download for Linux, Mac & Windows:

So, even in the add-on's current WIP state (which requires functions called must have no parameters and either return a 32-bit integer or nothing; and, a module must not require any external imports) it's still possible to do interesting things.

Interested to have people try out the project & to see what WASM execution functionality can enable for Godot with some concrete examples. Thanks!

@sunnystormy
Copy link

Hello! I'm another proponent of adding this feature to Godot by default. As someone who does hardware development with OpenSource ISAs (RISC-V, OpenPOWER) it would be useful to have a platform-agnostic binary that could be used to demonstrate graphical applications. Thank you!

@kirawi
Copy link

kirawi commented Sep 6, 2020

I'm interested too, but I have a feeling it won't be added for a while. In the big scheme of things, most people aren't using GDNative for their games.

@Frontrider
Copy link

Frontrider commented Sep 6, 2020

I'm interested too, but I have a feeling it won't be added for a while. In the big scheme of things, most people aren't using GDNative for their games.

Don't get me wrong, but if something is this tedious to set up, with this amount of extra steps (compared to alternatives it is like that) then of course it won't be widely used. Convenience is a big strength.

Webassemby at least has a merit of being fully integrateable to the editor as is, because you should be able to read the library in a more convenient way. It's not out of bounds to have a dropdown where you can just pick methods from the exported webassembly file, like "map my _ready function to the exported function unit_ready", because at worse (terrible solution) you can regex out the exported names from the textual representation unlike with other binary formats. The textual may even be enough for Godot, as we can build the binary as we package the game.

@fire
Copy link
Member

fire commented Sep 15, 2020

If we wanted to build wasm into godot engine, here's another approach:

Advantages:

  • Advantages of WASI. Runtime portabilility
    • AOT, JIT from wasm-micro-runtime
  • Can reuse GDNative
  • The runtime is in c++ so it has a high chance of being accepted.
  • NOT RUST

Disadvantages:

  • Probably slower?
  • C++ can be hard to use compared to rust

@GeorgeS2019
Copy link

GeorgeS2019 commented Oct 7, 2020

To all, I still not having the overview yet for Godot and WASM.
Is it possible to export Godot WASM with JavaScript callable methods and callback that allows the exported Godot WASM embedded in HTML5 as a Web Component serving as 3D Viewer?

If this can be done based on discussions in this thread, what will be the practical way to do that? This functionality serving as plugin? How to make that a plugin module. The plugin module essentially serve to broadcast events in godot 3D to outside world as callbacks and expose methods that allow outside JavaScript to access Godot internal Node properties and functions.

I value your feedback and suggestion.

@Calinou
Copy link
Member

Calinou commented Oct 7, 2020

Is it possible to export Godot WASM with JavaScript callable methods

Calling JavaScript code from GDScript is possible, but calling GDScript from JavaScript isn't (see #286).

callback that allows the exported Godot WASM embedded in HTML5 as a Web Component serving as 3D Viewer?

Godot's HTML5 export is designed to be on its own page. While you can customize the export template, it's not a Web Component you can place on arbitrary pages and expect it to work.

@GeorgeS2019
Copy link

@Calinou
During initialization, it is possible for OUTSIDE to pass in a series of string argument through engine.start()
By using GDScript call JavaScript, perhaps a way to redirect events and messages from within Godot to OUTSIDE.

Perhaps potentially, having a WASM as plugin that serve as the BRIDGE server between INSIDE and OUTSIDE. During Engine Init, the intended URL for the bridge server is being passed as argument for engine.Start().

I hope to use Godot as a sophisticated 3D viewer.

I do not yet have the overview, looking forwards for any other ideas.

@Calinou
Copy link
Member

Calinou commented Oct 7, 2020

@GeorgeS2019 Please use other community channels to ask support questions. This place is meant to discuss feature proposals; please don't derail them.

@fire
Copy link
Member

fire commented Nov 5, 2020

@follower Were you able to match the entire GDNative api? Was curious about your https://gitlab.com/RancidBacon/godot-wasm-engine implementation.

Last night we got WASM defined functions with arguments returning to Godot Engine. We're using https://github.com/bytecodealliance/wasm-micro-runtime.

@Zireael07
Copy link

@fire: Got a demo anywhere?

@MMMaellon
Copy link

Demo of the WASM stuff fire was talking about: https://drive.google.com/file/d/1CYvogO4F9URhvFvZIDsxyVQWVupymLcv/view?usp=sharing

Use the godot exe to open the project that's in the folder next to it and then hit run. WARNING: I never got around to fixing an issue with one of the particle systems. It's playing all the time and causes overdraw and lag. In the editor, zooming out all the way or disabling the particle system will fix this. In game, just keep moving so that the particles don't draw on top of each other. Sorry for the mess.

The source code for this demo is here: https://github.com/V-Sekai/WasGo/tree/main/demo

@kisg
Copy link

kisg commented Sep 29, 2021

With the implementation of the new GDExtension API it should be possible to integrate WASM into Godot quite well:

  • A WASI implementation of the GDExtension API needs to be provided
  • To the outside world the WASM code would look as a normal GDExtension module / class
  • When targeting the web, the WASM code would be linked into the main WASM module with the rest of the engine
  • A special case is the online editor, in this case a WASM interpreter needs to be embedded to allow the changes in the WASM code resources at runtime
  • When targeting all other platforms a WASI compatible WASM runtime needs to be embedded into the engine that will create the bridge between the WASM code and the engine.

@blockspacer
Copy link

@kisg
Awesome news!
Where can i find some usage examples or docs about WASI usage within godot engine?
Thank you in advance.

@kisg
Copy link

kisg commented Oct 7, 2021

@blockspacer AFAIK this suggestion with the GDExtension API (and the related #3370) is not implemented yet, my goal was to check if there is interest / objections from the core developer's side.
An equally important proposal is in my opinion #3369, which would simplify the engine considerably, but unfortunately it did not get much interest until now.

@hansondr
Copy link

hansondr commented Oct 6, 2022

Apologies for a bit of necromancy but as another option Wasmtime recently reached 1.0

@Frontrider
Copy link

Not just simplify the engine, but as a side effect also remove the "tear" that the engine currently has along c# and GDScript. Typed GDScript is even a good target for webassembly, as it does not need garbage collection.

@fire
Copy link
Member

fire commented Oct 6, 2022

I've been sketching how to do wasm based gdscript and other extensions based on c++ wasm3.

@kisg
Copy link

kisg commented Oct 6, 2022

Good to hear @fire. Do you intend to use the CodeGenerator interface in the GDScript runtime to emit WASM bytecode instead of GDScript bytecode? Would love to hear more. :)

@fire
Copy link
Member

fire commented Oct 6, 2022

You can check the repo here https://github.com/Geequlim/ECMAScript

@Frontrider
Copy link

Thinking about it, could it also allow Godot to focus more on GDScript's syntax and usability? Wasm is quite fast on it's own already. You can also try to integrate existing wasm optimizers instead of trying to develop an in-house solution.

Compilation speeds matter, but not as much as execution speed.

@Calinou
Copy link
Member

Calinou commented Oct 6, 2022

Thinking about it, could it also allow Godot to focus more on GDScript's syntax and usability? Wasm is quite fast on it's own already. You can also try to integrate existing wasm optimizers instead of trying to develop an in-house solution.

I don't think GDScript should depend on a WebAssembly runtime being available. There are likely cases where WebAssembly is not usable or only available in limited form (e.g. on consoles). Moreover, building the WebAssembly runtime from source is probably not easy, especially if you don't have a Rust toolchain installed. We want Godot to remain fast and easy to build from source after all 🙂

@kisg
Copy link

kisg commented Oct 7, 2022

@Calinou To be clear, I am not saying that the new GDScript interpreter should be thrown out.

But the concerns that you raise are not really an issue for a WASM-based runtime:

  • There are WASM runtimes written in C / C++, like WAMR, which has a very low footprint (~85K for interpreter and ~50K for AOT).
  • WASM would provide a very nice AOT compilation solution, that would be very beneficial for production builds, especially on consoles and mobile. It would also improve the performance on the web, if the whole project could be distributed as a single WASM module, with all the scripts precompiled in the WASM bytecode.

So I think that a WASM-based alternative runtime for GDScript would have a lot of benefits, and with the WASI standard already widely implemented, it would be straightforward to provide bindings to the rest of Godot inside the WASM runtime. Now that the GDScript Runtime has a nice abstraction for bytecode generation, it should be easier to create this alternative runtime.

@aunyks
Copy link

aunyks commented Mar 31, 2023

Hoping to keep this open. I compile the core simulation of my game to a WASM binary for portability and would love to use Godot as an interface for the sim (right now I use the web, Bevy, and raylib as interfaces that use the .wasm file).

@ManicMarrc
Copy link

Is there any news about this proposal?

@fire
Copy link
Member

fire commented Aug 12, 2023

https://github.com/ashtonmeuser/godot-wasm is an attempt in the area.

@fire
Copy link
Member

fire commented Feb 5, 2024

I was able to run blender on a wasi host with https://github.com/ktock/container2wasm.

This sample takes a blender container from New York Time's engineers and compiles it to a 1.5 gigabyte wasm file which is then loaded and executed. This is unoptimized, but shows how a WASI host can be used to load arbitrary amd64 and also riscv docker containers.

The blender command creates a monkey mesh primitive that is then saved as fbx.

In theory, Godot Engine containers should run too.

Although networking was described as working, I was only able to mount host to wasm directories and use stdio for the shell.

container2wasm gives a new promising use for WASI hosts.

.\c2w  -build-arg VM_MEMORY_SIZE_MB=1024 nytimes/blender:3.3.1-cpu-ubuntu18.04  blender.wasm
wasmtime --dir ../out::OUT -- blender.wasm blender -b --python-expr "import bpy; bpy.context.scene.render.fps = 30;bpy.ops.object.select_all(action='SELECT'); bpy.ops.object.delete(); bpy.ops.mesh.primitive_monkey_add(); bpy.ops.export_scene.fbx(filepath='/OUT/monkey.fbx')"

Here's an image of blender counting vertices.

image

@Frontrider
Copy link

Frontrider commented Feb 6, 2024

As someone who wants this, I think I drop one thing in on why it should NOT be officially supported yet.

Godot will NEED to support the web assembly component model, but it is not in a production ready phase yet.
https://component-model.bytecodealliance.org/

This is a must, because this lets Godot use all the existing (or ones that will exist) compiler infrastructure. Even if it would be restricted to one language for some reason, there is no real need to maintain the compilers specifically for this one engine.

And I still think that it is an amazing idea, as now it can let any "native extensions" to be running on any platform, because the maintenance cost for any given platform goes from "compiler for each language for each target" to "compile standard web assembly to the target's native code as needed".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests