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

Using wasm-bindgen for games #51

Open
17cupsofcoffee opened this issue Sep 3, 2019 · 9 comments
Open

Using wasm-bindgen for games #51

17cupsofcoffee opened this issue Sep 3, 2019 · 9 comments
Labels
Books/Tutorials/Guides Issues for explanatory content that's desired. Needs Champion We need someone who can help drive this forward.

Comments

@17cupsofcoffee
Copy link
Collaborator

17cupsofcoffee commented Sep 3, 2019

I've noticed while working on the wasm-bindgen backend for Tetra that there's a few rough edges around the tooling from a game dev perspective. Since wasm-bindgen seems to be the 'blessed' tool for WASM in Rust, having a tracking issue for some of these papercuts seems like a good idea. Maybe we can work with the WASM WG on some of these?

(Also, since some of said WG have been tagged in - aside from these issues, porting to WASM has gone ridiculously smoothly, kudos for all your hard work!)

Support for binary crates

wasm-bindgen doesn't currently support main - you have to use the wasm_bindgen(start) attribute on a public function instead, and that function can't be main (rustwasm/wasm-bindgen#1630). This means that it's not possible to have a binary crate 'just work' without some glue code.

My current approach is to have a macro that automatically creates a wasm_main wrapper, but I'd be interested to hear how other libraries (e.g. Winit) are planning on approaching this.

The above info is now out of date - wasm-bindgen supports binary crates now.

Most likely as a consequence of the above, wasm-pack is also currently quite heavily focused on usage for libraries that are intended for publishing to NPM. There's an RFC for a --no-pack mode (rustwasm/wasm-pack#691) that looks like it might work better for our use cases, but it seems to have stalled a little bit.

No cargo web counterpart

The stdweb ecosystem has cargo web, which is a really nice tool that offers a HTTP server, auto-reloading, static file packaging, etc. Unfortunately, it doesn't currently support wasm-bindgen projects (koute/cargo-web#92).

There are templates for projects that call into wasm-pack from Webpack and offer similar features in that way, but I feel like this is overkill for most gamedev needs - 99% of the time, you just want a HTML page with a canvas on it that you can hook into.

EDIT: Actually, it looks like cargo web might have added wasm-bindgen support of some kind since I last tried it! Need to give that a proper try. Nope, it was stdweb that added support, my mistake!

@Pauan
Copy link

Pauan commented Sep 3, 2019

@17cupsofcoffee
Copy link
Collaborator Author

Okay, I think I get the state of things now (please correct me if I'm wrong!) - you can use stdweb with wasm-bindgen or cargo web as the backend, but you can't use cargo web with wasm-bindgen (at least not without manually calling the latter after the former).

@fitzgen
Copy link

fitzgen commented Sep 3, 2019

Most likely as a consequence of the above, wasm-pack is also currently quite heavily focused on usage for libraries that are intended for publishing to NPM.

I wouldn't characterize it this way. It has a publish command to publish the package to npm, but it is an optional command and doesn't affect anything else.

wasm-bindgen doesn't currently support main - you have to use the wasm_bindgen(start) attribute on a public function instead

This is because there fundamentally is no main on the web. When main exits, basically nothing else runs. When a wasm_bindgen(start) function exits, the page has still only just loaded.

HTTP server

We have some ideas around this stuff, but unfortunately haven't gotten around to it yet: rustwasm/rfcs#10

@Pauan
Copy link

Pauan commented Sep 4, 2019

@fitzgen It has a publish command to publish the package to npm, but it is an optional command and doesn't affect anything else.

That's true, but even the wasm-pack build command is optimized for libraries. You can contrast that with cargo web build, which is optimized for applications.

Having used both, I (and many others) have found that cargo web provides a much smoother experience for application developers. Everything Just Works.

There's a lot that wasm-bindgen (and wasm-pack) need to learn from cargo web and stdweb, because they provide a much nicer, smoother, more Rust-like experience.

This is because there fundamentally is no main on the web.

That's not the reason we don't support bin crates. After all, cargo web has no problem with supporting bin crates (everything Just Works in the same way that Rust itself does), and wasm_bindgen(start) is effectively a main.

The reason we don't support bin crates is because it bloats up the file size by a lot. After that is fixed in rustc we'll be able to support bin crates.

@grovesNL
Copy link

grovesNL commented Sep 4, 2019

Maybe it would benefit the rust-gamedev WG if we could try to clarify the following points:

  1. Whether users should typically use wasm-pack, or instead use wasm-bindgen-cli directly. I remember there were some questions about keeping wasm-bindgen-cli and wasm-bindgen in sync when using the CLI directly.
  2. How webpack and npm relate to various parts of the wasm toolchain (and how to avoid them if the application prefers not to use them). I think --web was (or still is?) the standard way to do this but there were some changes earlier this year. This is slightly related to the first point.
  3. How to handle crates that want to support both stdweb/wasm32-unknown-unknown and wasm-bindgen/wasm32-unknown-unknown
  4. How to handle non-Rust dependencies even when targeting wasm32-unknown-unknown (i.e. a dependency on a C or C++ library which is still built with Emscripten), even if the answer is to try to avoid doing that. This question has already come up a few times in the Rust community Discord. It's especially confusing for handling resources/assets (for example, we might call the separate Emscripten bundle a regular resource that has to be loaded and executed).

This clarification would be super useful to improve the documentation for gfx-hal's quad example and glow.

@JeanMertz
Copy link

To add a small experience report to this discussion. I'm not using wasm-bindgen for games, but am writing an application using it.

It's been a few months since I started it, but I too remember some confusion about how to use the tooling for applications instead of libraries. At some point I had been messing with it for a while and decided to look into stdweb because its approach seemed much easier to grok, but had to move away from it because some dependencies I wanted to use didn't support using stdweb (which also, as a first-time experience, made me a bit weary of potential ecosystem fragmentation).

I'm not sure if that's still the case with the recent convergence, but at some point I got things to "just work" using wasm-bindgen but without using wasm-pack, and haven't really looked into the pipeline since, so long as things keep working.

My current set-up now runs several tools in succession to build a release binary, including cargo build, wasm-snip, wasm-bindgen and wasm-opt. It then uses this inline module code to make things work (although I'm investigating an issue running the application in Safari which might be related to this, so this might change).

I have very little experience with the build ecosystem that exists around JavaScript, and didn't want to spend too much time on that for this project, so the goal was to not have to deal with anything related to that, which in the end seems possible, but it took some digging and experimenting to make it all work.

@scottjmaddox
Copy link

I'm using wasm-pack for my web-based multiplayer game https://SneakySnake.io. A couple thoughts:

  1. On binary support: this would be better handled with a template project that configures npm, webpack, and wasm-pack appropriately, sets up an auto-scaled canvas with high-dpi support, WebGL context, and calls into init and update_and_render functions (or similar) in the wasm. You're better off writing your game as a library, anyways, if you ever want to run it on anything other than the web. I highly recommend watching Handmade Hero to see how Casey does multi-platform support.

If I ever have time to open source any of my work on SneakySnake, maybe I'll make one of these for others to benefit from. But all my code is currently highly specialized to this project's particular needs, i.e. decoupled network/update tick and render tick rates.

  1. On http server and auto-reload, as pointed out in the OP, this is all covered by an appropriately configured webpack/wasm-pack environment.

@Lokathor
Copy link
Member

I'm strongly in favor of the handmade hero approach, and I think it's one place where we can easily get a win out of this WG.

@boringcactus
Copy link

rustwasm/wasm-bindgen#1630 has been closed, making binary crates Just Work in wasm-bindgen; once those changes get released I'll see if I can push harder for wasm-pack to also Just Work on binary crates, which will knock out the first major obstacle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Books/Tutorials/Guides Issues for explanatory content that's desired. Needs Champion We need someone who can help drive this forward.
Projects
None yet
Development

No branches or pull requests

8 participants