magnum
magnum copied to clipboard
EmscriptenApplication doesn't play well with asyncify
Reported by @ShaddyDC. Current workaround is using Sdl2Application
instead.
Repro code -- after pressing the button, the value is printed, but Frame
isn't anymore after that. WindowFlag::AlwaysRequestAnimationFrame
doesn't help.
#include <emscripten.h>
EM_JS(int, get_digest_size, (const char* str), {
// Note how we return the output of handleSleep() here.
return Asyncify.handleSleep(function(wakeUp) {
const text = UTF8ToString(str);
const encoder = new TextEncoder();
const data = encoder.encode(text);
out("ask for digest for " + text);
window.crypto.subtle.digest("SHA-256", data).then(digestValue => {
out("got digest of length " + digestValue.byteLength);
// Return the value by sending it to wakeUp(). It will then be returned
// from handleSleep() on the outside.
wakeUp(digestValue.byteLength);
});
});
});
void ImGuiExample::drawEvent() {
GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);
_imgui.newFrame();
Debug{} << "Frame";
/* Enable text input, if needed */
if(ImGui::GetIO().WantTextInput && !isTextInputActive())
startTextInput();
else if(!ImGui::GetIO().WantTextInput && isTextInputActive())
stopTextInput();
{
const char* silly = "some silly text";
static int value = 0;
ImGui::Text("%s's digest size is: %d\n", silly, value);
if(ImGui::Button("load")){
value = get_digest_size(silly);
Debug{} << value;
}
}
/* Update application cursor */
_imgui.updateApplicationCursor(*this);
_imgui.drawFrame();
swapBuffers();
redraw();
}
@Squareys since you were originally implementing the idle loop, do you have any idea what could cause this?
It also affects functions like emscripten_wget_data
. After an asincify operation, future frames aren't requested anymore and the application freezes. Manually requesting the next frame draw seems to work around it. Code copied from here
if(ImGui::Button("load")){
value = get_digest_size(silly);
Magnum::Debug() << value;
int (*_callback)(void*);
_callback = [](void* userData) -> int {
auto& app = *static_cast<ImGuiExample*>(userData);
app.drawEvent();
return true;
};
EM_ASM({
/* Animation frame callback */
var drawEvent = function() {
var id = window.requestAnimationFrame(drawEvent);
/* Call our callback via function pointer returning int with two
int params */
if(!dynCall('ii', $0, [$1])) {
window.cancelAnimationFrame(id);
}
};
window.requestAnimationFrame(drawEvent);
}, _callback, this);
}