Open7

WebGL-Native: Raspberry Piで起動しない問題

okuokuokuoku

prev: https://zenn.dev/okuoku/scraps/d4419915c37216
next:

よもやこんな苦労するとは。。

起動時に刺さる

ひとまず現状見えている問題は:

  1. Raspbian OSに収録されているOpenGLが正常に起動しないこれは手でビルドしたら治った ので、たぶんSDL2が自分でロードするOpenGLと、実行ファイルがリンクしているOpenGLが一致していないのが問題だろう。
  2. Emscriptenの stdout が何故かソケットに繋がっている 。意味わかんねぇ! ただ、これはNode.jsやUbuntu amd64上のduktapeでも同様になっていることを確認したのでたぶん問題ではない。
  3. 2 のソケットを経由して stdout に書こうとして EDESTADDRREQ を返却すると先に進まなくなる 。これはRaspberry Pi上のduktapeでしか起こらない。 WebGLコンテキストの生成中に進まなくなったように見えていた のはこれが原因だった。

とりあえず 3 を解く必要がある。

okuokuokuoku

Raspberry Pi 3 に挿しかえる

Raspberry Pi 1とRaspberry Pi 3はソフトウェア的には互換なので、RPi1で使っていたSDカードをRPi3に挿しても普通に起動する。というわけでRPi1ではメモリ不足で使えなかった gdb が使えるようになった。

まぁゲーム機でも開発機は実機の倍のメモリを搭載したりしてるんで、こういうインチキは許して。。

okuokuokuoku

符号付き数のオーバーラップが問題だった

https://github.com/okuoku/cwgl-proto/commit/756cbdc5f9e12ffdf1ffa477bb819c30dc54dfb2

diff --git a/duk-nccc/duk-nccc.c b/duk-nccc/duk-nccc.c
index 0021715..9fe2f6f 100644
--- a/duk-nccc/duk-nccc.c
+++ b/duk-nccc/duk-nccc.c
@@ -82,7 +82,7 @@ value_out(duk_context* ctx, uint64_t* out, char type, duk_idx_t vin){
             }else if(get_pointer(ctx, vin, &v)){
                 *out = v;
             }else{
-                *out = duk_require_number(ctx, vin);
+                *out = (int64_t)duk_require_number(ctx, vin);
             }
             break;
         case 'f':

gdb でステップ実行してみると、(エラーにより) -89 を返却すべきところで 0 を返却していることがわかった。で、これは double-89.0uint64_t にキャストしているのが原因のようなので、上記のように修正することで期待通りに動作するようになった。

... x86と挙動が違うのかコレ。。

okuokuokuoku

画面が壊れる問題

というわけで無事OpenGLで描画する所までは進行したものの、画面にゴミを表示して止まってしまった

こんなもんどうやってデバッグすればいいんだ。。

前回OpenGLスタックを手でリビルドしている ので、それをRaspberryPi OS本来のものに戻してみるのかな。。

止まり方はかなり深刻な感じで、おそらくGPU側をハングさせてしまっている。この状況になると、SSHやコンソールも一切操作できなくなる。(非特権ユーザがシステム全体を止められてしまうことになる)

okuokuokuoku

クラッシュ箇所は判明したが。。

とりあえずテクスチャのアップロードが原因であることは分かった。

この行を実行するとカーネルパニックする。

ちょっと芸術的な壊れ方だな。

#0  droppoint () at /home/pi/repos/cwgl/yfrm/src-sdl2/yfrm-ctx-sdl2.c:115
#1  cwgl_priv_check_current (ctx=0x411e20)
    at /home/pi/repos/cwgl/yfrm/src-sdl2/yfrm-ctx-sdl2.c:115
#2  0x76b9db20 in cwgl_texImage2D (ctx=<optimized out>,
    target=(CWGL_ENUM_DUMMY), level=2, internalformat=(CWGL_ENUM_DUMMY),
    width=512, height=512, border=0, format=(CWGL_ENUM_DUMMY),
    type=(CWGL_ENUM_DUMMY), buf=0x5d824af0, buflen=1048576)
    at /home/pi/repos/cwgl/src-gles2/cwgl-gles2-s3.c:58
#3  0x7690ad90 in stub_cwgl_texImage2D (in=<optimized out>,
    out=<optimized out>) at /home/pi/repos/cwgl/ncccstubs/stubcode.inc.c:61
#4  0x00015494 in nccc_call_trampoline (ctx=0x68918)
    at /home/pi/repos/cwgl/duk-nccc/duk-nccc.c:235
#5  0x00019c18 in duk__handle_call_raw (thr=thr@entry=0x68918,
    idx_func=idx_func@entry=10, call_flags=call_flags@entry=8)
    at /home/pi/repos/cwgl/duktape260/duk_js_call.c:2268

level=2 の指定から、MIPMAPが怪しいか。。?確かに level == 0 のものだけ通すようにしたらクラッシュはしなくなった。

しかし、このまま実行を続けても、

-------- GLSL link error: ERROR:CUSTOM-6 (fragment shader, line -1) Out of memory

のように出てシェーダのコンパイルに失敗してしまった。

okuokuokuoku

Full KMS + SDL2 KMSDRM で試す

BroadcomのGLESを使うのは諦めてMesaを使うことにした。現実的なワークロードを動かすのはもう無理だな。。(Broadcomのスタックと違い、MesaはOpenGL実装をCPU側で行っていて、3D描画のみをGPUにオフロードするのでちょっと重い。)

結果 amd64 Linuxと同じくDevelopment buildと黒画面に出る ところまでは動作した。

ただamd64では正常に描画される状態まで持っていけたものの、Raspberry Piの方ではDRI内部でクラッシュしてしまう。

CNT: 2218

Thread 1 "yuniduk" received signal SIGSEGV, Segmentation fault.
0x596426b4 in ?? () from /usr/lib/arm-linux-gnueabihf/dri/vc4_dri.so
(gdb) bt
#0  0x596426b4 in ?? () from /usr/lib/arm-linux-gnueabihf/dri/vc4_dri.so
#1  0x00000028 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

とりあえず 2218 回目のOpenGL callでbreakしてみる:

Thread 1 "yuniduk" hit Breakpoint 1, droppoint ()
    at /home/pi/repos/cwgl/yfrm/src-sdl2/yfrm-ctx-sdl2.c:108
108         printf("Reached droppoint.\n");
(gdb) bt
#0  droppoint () at /home/pi/repos/cwgl/yfrm/src-sdl2/yfrm-ctx-sdl2.c:108
#1  0x76b80f34 in cwgl_priv_check_current (ctx=0x568468)
    at /home/pi/repos/cwgl/yfrm/src-sdl2/yfrm-ctx-sdl2.c:115
#2  0x76b82a28 in cwgl_drawElements (ctx=0x568468, mode=(CWGL_ENUM_DUMMY),
    count=5190, type=(CWGL_ENUM_DUMMY), offset=0)
    at /home/pi/repos/cwgl/src-gles2/cwgl-gles2-s2.c:81
#3  0x7682ed78 in stub_cwgl_drawElements (in=0x7effe060, out=0x7effe060)
    at /home/pi/repos/cwgl/ncccstubs/stubcode.inc.c:61

... ただの描画。。つまりメモリ不足だな。。 MESA_DEBUG=1 して実行すると、

CNT: 788
Mesa: User error: GL_OUT_OF_MEMORY in glTexImage
Mesa: User error: GL_OUT_OF_MEMORY in glTexImage2D
CNT: 789