-
Notifications
You must be signed in to change notification settings - Fork 30
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
Thoughts on Asyncify #24
Comments
Possible without using AsyncIt is theoretically possible to solve some cases of the API without using async, however blocking for arbitrary promises/callbacks is not possible due to the nature of the single core JavaScript execution model. TexturesOne could run a synchronous XMLHttpRequest, parse the image manually and put it Base64 encoded into the src attribute of the image tag. I don't know whether this synchronously sets the width height automatically but I doubt it. You probably have to parse the width/height manually as well. FontsCould be achieved the same way raylib does it in C by loading the font synchronously (XMLHttpRequest) and then restarting it into a texture (as described above). Impossible without AsyncAs teased above, actively waiting for promises to finish does not work in JavaScript. You can't block like this: // Does NOT work
function block(promise) {
let running = true;
let result = undefined;
async function runner() {
result = await promise;
running = false;
}
runner();
// Will never terminate, because this while loop blocks the runner from finishing
while (running);
return result;
}
// Blocks forever
const fetchedResult = block(fetch("./img.png"));
|
IMO the simplest use of asyncify for this project would be to make BeginDrawing() {
if(!this.animframe){ // or read from __asyncify_state global
// comes from regular call from wasm
window.requestAnimationFrame((timestamp) => {
this.dt = (timestamp - this.previous)/1000.0;
this.previous = timestamp;
//this.draw_ptr needs to be a location into wasm memory that can hold 2 pointers.
this.wasm.instance.exports.asyncify_start_rewind(this.draw_ptr);
window.requestAnimationFrame(next);
this.animframe = true;
this.wasm.instance.exports.main();
this.wasm.instance.exports.asyncify_stop_unwind(this.draw_ptr);
});
this.wasm.instance.exports.asyncify_start_unwind(this.draw_ptr);
return;
} else {
//comes from rewind.
this.wasm.instance.exports.asyncify_stop_rewind(this.draw_ptr);
this.animframe = false;
return; //regular return;
}
} this corresponds better I believe with the semantics of raylib where beginDraw actually sets up the state for drawing. |
This is a nice full example👍 I will try this out as well. However in regards to semantics, I have checked |
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 fromasyncify-wasm
package's GitHub):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):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:The text was updated successfully, but these errors were encountered: