Skip to content

Thoughts on Asyncify #24

Open
Open
@AntonPieper

Description

@AntonPieper

Asyncify

Because native Web assembly does not yet support pausing and resuming, folks have invented Asyncify to transform wasm code to allow stack unwinding and rewinding. Most people use Asyncify with emscripten, but as far as I can tell, Asyncify is completely implemented through binaryen.

It can be used without emscripten through wasm-opt (taken from asyncify-wasm package's GitHub):

wasm-opt --asyncify [-O] [--pass-arg=asyncify-imports@module1.func1,...] in.wasm -o out.wasm

Then on the JavaScript side, you can use exports.asyncify_start_rewind(...) and the like to use asyncify.

The package asyncify-wasm makes this simpler and allows "just" using async functions (promises) in the implementation of imported functions (example also taken from README.md):

let { instance } = await Asyncify.instantiateStreaming(fetch('./out.wasm'), {
  get_resource_text: async url => {
    let response = await fetch(readWasmString(instance, url));
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    return passStringToWasm(instance, await response.text());
  }
});

await instance.exports._start();

Relevance for project

This could allow using literally the same code for native and web without any modifications (no GameFrame) to the examples at the cost of an extra build step (wasm-opt) and some performance (instrumentation from asyncify).

One could implement WindowShouldClose as a promise that resolved on the next frame:

{
  async WindowShouldClose() {
    return new Promise((resolve) => {
        /* ... */
        requestAnimationFrame(() => resolve(/* ... */)):
    });
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions