てけもぐ Tech 忘備録

wasm で簡単な物理シミュレーションを書いてみた話 - emscripten

対象

wasm 初学者

内容

Wasm で載せた簡単な粒子のシミュレーションの覚え書きの続き。前の記事はこちら

出来たものはこちら

emscripten を使ってC++ のコードを wasm にする時の、コンパイラオプションが地味に?試行錯誤したので、覚えている内に記録しておきます。ろくにマニュアルを読まないでやったからかもしれません。

以下 cmake の抜粋。

target_compile_options(${PROJECT_NAME} PRIVAT
    "-msimd128"
    "-sUSE_PTHREADS=1"
)

リンカーオプションの方は、

target_link_options(${PROJECT_NAME} PRIVATE 
    "-sUSE_SDL=3"
    "-sUSE_SDL_TTF=3"
    "-sEXPORTED_RUNTIME_METHODS=['PThread']"
    "-sEXPORTED_FUNCTIONS=['_main', '_stop_loop']"
    "-sMODULARIZE=1"
    "-sEXPORT_NAME=ParticlesModule"
    "-sUSE_PTHREADS=1"
    "-sENVIRONMENT=web"
    "-sPTHREAD_POOL_SIZE=4"
    "-sPROXY_TO_PTHREAD=1"
    "-sALLOW_BLOCKING_ON_MAIN_THREAD=0"
    "-sOFFSCREENCANVAS_SUPPORT=1"
    "-sEXIT_RUNTIME=1"
    "SHELL:--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/assets@/assets"
    "-sALLOW_MEMORY_GROWTH=0"
)

0でセットされているものなど、中にはなくてもいいやつもある。


USE_PTHREAD はスレッド使っているので必須。OFFSCREENCANVAS_SUPPORT は、PROXY_TO_PTHREAD と一緒に使う必要があった。

後始末が結構難しくて、C++ の方で後始末をしようとしてスレッドの終了を join()で待つと、ブラウザのメインスレッドをブロックするな!と怒られる。PROXY_TO_PTHREAD をやっていてもこれは同じ。SDL 側の後始末も同じ様に出来ない。仕方ないので thread を直接 emscripten の javascript コードを使って強制終了させました。 PThread.terminateAllThreads() とか、PThread.unusedWorkers.forEach((w: Worker) => w.terminate())とか、 pthread.workder.terminate() で。
それから、javascript 側のソースへの参照を切って、ブラウザに回収してもらう。
C++ の方を折角スマートポインタで書いても、使われないんでしょうねこれ。
もしかしたら、detach したら行けるのかもですけど、SDL の後始末方も引っかかると思われます。
多分いいやり方を私が知らないだけでしょう。

asset というのは、フォントのパスをマップするのに使っていて、@マークがデリミタ。

MODULARLIZE=1にはなっているけれど、EXPORT_ES6 を使ってやろうとするとうまく行かず、仕方ないので script.src に wasm の javascript を貼り付けて使用。