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

Support Emterpreter #70

Open
Beuc opened this Issue Jan 22, 2019 · 7 comments

Comments

Projects
None yet
3 participants
@Beuc
Copy link
Contributor

Beuc commented Jan 22, 2019

Currently SDL2 needs to be locally patched in order to leverage Emterpreter's emscripten_sleep().
Ideally SDL2 would support Emterpreter out of the box.

See https://groups.google.com/forum/#!topic/emscripten-discuss/v1w6PGYhNOA for a rationale.

For reference, here is my local patch:

diff --git a/src/timer/unix/SDL_systimer.c b/src/timer/unix/SDL_systimer.c
index 159bda5c5..222a7455b 100644
--- a/src/timer/unix/SDL_systimer.c
+++ b/src/timer/unix/SDL_systimer.c
@@ -31,6 +31,8 @@
 #include "SDL_assert.h"
 #include "../SDL_timer_c.h"
 
+#include <emscripten.h>
+
 /* The clock_gettime provides monotonous time, so we should use it if
    it's available. The clock_gettime function is behind ifdef
    for __USE_POSIX199309
@@ -187,6 +189,10 @@ SDL_GetPerformanceFrequency(void)
 void
 SDL_Delay(Uint32 ms)
 {
+#ifdef __EMSCRIPTEN__
+    emscripten_sleep_with_yield(ms);
+    return;
+#else
     int was_error;
 
 #if HAVE_NANOSLEEP
@@ -225,6 +231,7 @@ SDL_Delay(Uint32 ms)
         was_error = select(0, NULL, NULL, NULL, &tv);
 #endif /* HAVE_NANOSLEEP */
     } while (was_error && (errno == EINTR));
+#endif /* __EMSCRIPTEN__ */
 }
 
 #endif /* SDL_TIMER_UNIX */
diff --git a/src/video/emscripten/SDL_emscriptenopengles.c b/src/video/emscripten/SDL_emscriptenopengles.c
index fe5e07342..6cd6a0e5f 100644
--- a/src/video/emscripten/SDL_emscriptenopengles.c
+++ b/src/video/emscripten/SDL_emscriptenopengles.c
@@ -95,9 +95,16 @@ Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context)
 }
 
 SDL_EGL_CreateContext_impl(Emscripten)
-SDL_EGL_SwapWindow_impl(Emscripten)
 SDL_EGL_MakeCurrent_impl(Emscripten)
 
+int
+Emscripten_GLES_SwapWindow(_THIS, SDL_Window * window)
+{
+    EGLBoolean ret = SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
+    emscripten_sleep_with_yield(0);
+    return ret;
+}
+
 void
 Emscripten_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
 {

Emterpreter whitelist:

-s EMTERPRETIFY_WHITELIST='[..., "_SDL_WaitEvent", "_SDL_WaitEventTimeout", "_SDL_Delay", "_SDL_RenderPresent", "_GLES2_RenderPresent", "_SDL_GL_SwapWindow", "_Emscripten_GLES_SwapWindow", ...]'
@Daft-Freak

This comment has been minimized.

Copy link
Member

Daft-Freak commented Jan 22, 2019

Hmm... Maybe we could make nanosleep call emscripten_sleep_with_yield when using Emterpreter? (Possibly with a new option)

@Beuc

This comment has been minimized.

Copy link
Contributor Author

Beuc commented Jan 22, 2019

Maybe.
That wouldn't distinguish between emscripten_sleep and emscripten_sleep_with_yield.
Also that wouldn't take care of SwapWindow.

@Daft-Freak

This comment has been minimized.

Copy link
Member

Daft-Freak commented Jan 22, 2019

Wouldn't we have the yield vs non-yield issue regardless of where we implemented this though? That was part of why I was suggesting an option (something like -s YIELD_IN_NANOSLEEP=1). For SwapWindow, we could do something in eglSwapBuffers. (Though, we'll need something for the software renderer as well).

@Beuc

This comment has been minimized.

Copy link
Contributor Author

Beuc commented Feb 1, 2019

An issue with adding code in nanosleep is that libc.bc is cached. This needs additional logic in Emscripten to ensure a new libc variant is used.

Another issue with eglSwapBuffers is that it's implemented in JavaScript, and resuming to JavaScript is not supported by Emterpreter. I used to add a emscripten_sleep_with_yield in library_elg.js and that appeared to work, but the behavior is not specified. That's why I moved to call back to SDL2, in C.
I keep getting random Emterpreter crashes in my application so I'd rather not take chances.

For reference, Alon suggests (cf. mailing-list link) implementing a hook in SDL2 that would be initialized with a no-op and redefined at run-time.

I don't have a definite opinion on this.

@Daft-Freak

This comment has been minimized.

Copy link
Member

Daft-Freak commented Feb 1, 2019

I don't know much about Emterpreter, so @kripken probably has a better idea of what would work here than me. As long as whatever we come up with doesn't require multiple SDL builds I don't really mind where it's done.

@kripken

This comment has been minimized.

Copy link
Member

kripken commented Feb 1, 2019

I think we can apply that patch to SDL, so that emscripten_sleep_with_yield is called in all those cases. And we can make emscripten do nothing in that function when the emterpreter is disabled (that may already be the case now - if not, we just need to add it as an empty function), and the normal emterpreter behavior otherwise. That should just work with a single SDL2 build, and the user specifies -s EMTERPRETIFY=1 at link time optionally.

@Daft-Freak

This comment has been minimized.

Copy link
Member

Daft-Freak commented Feb 4, 2019

We would still need the sleep in SDL_Delay to delay in a non-emterpreter build though. (And we'll need an emscripten_sleep_with_yield in Emscripten_UpdateWindowFramebuffer for the software renderer.)

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