emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.75k stars 3.3k forks source link

SDL2 application will break when using pthreads #6009

Open aliasdevelopment opened 6 years ago

aliasdevelopment commented 6 years ago

I have made a SDL2 application using the linker flag "-s USE_SDL=2" which works as expected. I have made a ASIO application using https://github.com/emscripten-ports/asio which works as expected. I have made a ASIO/pthread application with works as expected using the linker flags "-s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=4 -s PROXY_TO_PTHREAD=1"

But I can not merge these applications together. It seems as if USE_SDL and USE_PTHREADS/PROXY_TO_PTHREAD works against each other. I known that many older tutorials states that multithreading is not possible, but also knows that a lot of activities has been done to change this.

I get the following error when combining SDL and pthreads: pthread-main.js onmessage() captured an uncaught exception: ReferenceError: screen is not defined

I can understand that I would make sense that the resources for rendering would only be available for the main thread, but pthread is missing some features/resources for SDL to possible.

Is it by design that USE_SDL and USE_PTHREADS/PROXY_TO_PTHREAD work against each other? Would it be possible to use SDL from the main thread and still use pthreads for additional work?

jakogut commented 5 years ago

I'm encountering this same issue. USE_SDL and USE_PTHREAD/PROXY_TO_PTHREAD seem to be incompatible.

jakogut commented 5 years ago

Digging into the issue further, the stack trace shows:

ReferenceError: screen is not defined
    at Array.ASM_CONSTS (http://localhost:6931/test.js:1501:32)
    at _emscripten_asm_const_i (http://localhost:6931/test.js:1526:26)
    at _Emscripten_VideoInit (wasm-function[17363]:43)
    at _SDL_VideoInit (wasm-function[17486]:635)
    at _SDL_InitSubSystem (wasm-function[17481]:203)
    at _SDL_Init (wasm-function[17612]:3)
    at _main (wasm-function[310]:133)
    at Module._main (http://localhost:6931/test.js:11418:75)
    at ___call_main (http://localhost:6931/test.js:1877:24)
    at ___emscripten_thread_main (wasm-function[18150]:23)
onmessage @ test.worker.js:181

Looking at the Emscripten port of SDL2, video/emscripten/SDL_emscriptenvideo.c:145:

mode.w = EM_ASM_INT_V({
    return screen.width;
}); 

mode.h = EM_ASM_INT_V({
    return screen.height;
}); 

So it seems that the Emscripten_VideoInit function tries to get the screen dimensions from the JS object screen, but the object isn't being proxied to the new thread main is running in.

jakogut commented 5 years ago

I've resolved the issues with proxying EM_ASM calls in the sdl2 port (my fixes are available at https://github.com/jakogut/SDL2/tree/sdl2-proxy-pthread-fixes), now I'm getting:

TypeError: Cannot read property 'getContext' of undefined
    at Object.createContext (http://localhost:6931/test.js:6608:19)
    at _eglCreateContext (http://localhost:6931/test.js:6793:24)
    at _SDL_EGL_CreateContext (wasm-function[17463]:337)
    at _Emscripten_GLES_CreateContext (wasm-function[17453]:12)
    at _SDL_GL_CreateContext (wasm-function[17025]:143)
    at _GLES2_CreateRenderer (wasm-function[17017]:489)
    at _SDL_CreateRenderer (wasm-function[17662]:303)
    at _main (wasm-function[388]:376)
    at Module._main (http://localhost:6931/test.js:12316:33)
    at ___call_main (http://localhost:6931/test.js:2000:24)

Doing a little digging around seems to indicate that the EGL code at src/library_egl.js is unable to access the canvas object, probably because those calls need proxied as well. @kripken, can you shed any light on this issue?

kripken commented 5 years ago

This may be stuff that has not been proxied yet, yes - @juj can confirm.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 7 days. Feel free to re-open at any time if this issue is still relevant.

kripken commented 4 years ago

Looks like the PR for this is https://github.com/emscripten-core/emscripten/pull/9336 - would be good to get that landed. @jakogut - is there something blocking it?

jakogut commented 4 years ago

@kripken No blockers, just have to address the feedback given. I can look at doing that later this week.

Hossein-Noroozpour commented 4 years ago

Hi, is there any update for this issue?

janpaul123 commented 3 years ago

For those coming across this, it looks like https://github.com/emscripten-ports/SDL2/pull/127 is still open.

SoapyMan commented 3 years ago

So question is... when? 😅

zengming00 commented 3 years ago

I ran into the same problem when I added network support to a working SDL2 project

10665

13755

puzzlepaint commented 2 years ago

I ran into this issue as well and would add +1 for merging emscripten-ports/SDL2#127 which seems to fix it.

flyingllama87 commented 2 years ago

+1 running into this issue.

HarrievG commented 2 years ago

+1 , But , retrieving the size from screen can be replaced with just Module['canvas'].width/height -edit- There are way more problems in emscripten land to be fixed than this one.

Besides the screensize, mouse locking crashes, and all of the EGL calls proxy to main, which makes using EGL on a thread not really feasible. (Fixable by removing every async property from EGL.js lib) Besides the EGL issues, openAL is totally unusable since that proxies everything. Proxy can be removed from some calls, but not all as is with the egl case.

Long story short, emscripten is not ready for production level threading work that needs to be performance critical. Without significantly editing the js libraries,the best bet is to only use calls in thread things that are not in the emscripten libraries. Or, to use asyncify smartly and make it work on an single thread.

connorjclark commented 2 years ago

There is a fix available for using PROXY_TO_PTHREAD with SDL, if you are willing to use a fork and hack a bit. @Daft-Freak did this amazing work. here's how to use it today, in case this is a blocker for you:

  1. open your emscripten installation tools/ports/sdl2.py
  2. set TAG to a93fc312a87cc2a94ce19bedec8ba846a6ee50e4
  3. set HASH to cc47eca26d647d4aee2d4fb2e8565a3bad490dcf3a364cca139e8cda275c0a2d0d60aa198164b3f2d03111df06c836d22158c5764b204d8fab2af98292e40de7
  4. change L23 to use https://github.com/Daft-Freak/SDL/archive/
  5. add SDL_list.c to L31
  6. delete your cached libsdl library, and run embuilder build sdl2
  7. in cache/ports/sdl2/SDL-a93fc312a87cc2a94ce19bedec8ba846a6ee50e4/src/audio/emscripten/SDL_emscriptenaudio.c change L259 to use MAIN_THREAD_EM_ASM_INT

After that, you should be able to run SDL compiled with PROXY_TO_PTHREAD and OFFSCREENCANVAS_SUPPORT.

Although, I have noticed some issues re: audio locking the main thread if you have MAIN_THREAD_* proxy calls.

magne4000 commented 1 year ago

Is this still an issue since https://github.com/libsdl-org/SDL/pull/5365 has been merged?

connorjclark commented 1 year ago

Fixing your link: https://github.com/libsdl-org/SDL/pull/5365

I believe https://github.com/libsdl-org/SDL/pull/6142 is what may have resolved this, which I think incorporated the changes I suggested to the author in my previous comment.