前回 Cortex-A15 の動作だけ極端に低速で少々疑問が残る結果となりました。
RAM 1MB の端末でも動くようになったのでさらに調べてみました。
Tegra4 Cortex-A15 Firefox 60fps 以上 (Tegra Note 7) Tegra3 Cortex-A9 Firefox 20~47fps (Nexus 7 2012)
今回の結果を見る限り、Cortex-A15 でも Krait 並に高速に動作していることがわかります。
また Cortex-A9 も予想よりも速い印象です。
上の両機種とも画面解像度が低く 1280×800 dot です。
前回速度が出なかった Nexus 10 は 2560×1600 と非常に解像度が高いので、
ブラウザが何らかの解像度に応じた CPU 転送を行っている可能性もあります。
なお内部のレンダリング解像度は 960×640 固定です。
以下詳細データ
1. 960x640 63万Tri+Animation Tegra4 Cortex-A15 Firefox 60fps 以上 (Tegra Note 7) Tegra3 Cortex-A9 Firefox 20fps 前後 (Nexus 7 2012) 2. 960x640 63万Triangles Tegra4 Cortex-A15 Firefox 60fps 以上 (Tegra Note 7) Tegra3 Cortex-A9 Firefox 25fps 前後 (Nexus 7 2012) 3. 960x640 6万Triangles Tegra4 Cortex-A15 Firefox 60fps 以上 (Tegra Note 7) Tegra4 Cortex-A15 Chrome 12fps 以上 (Tegra Note 7) Tegra3 Cortex-A9 Firefox 47fps 前後 (Nexus 7 2012) Tegra3 Cortex-A9 Chrome 8fps 前後 (Nexus 7 2012) K3V2 Cortex-A9 Firefox 描画崩れ (dtab) K3V2 Cortex-A9 Chrome 動作せず (dtab) ・fps が大きい方が高速
Tegra3 は JavaScript の動作にはまだ余裕があるものの、
明らかに GPU 性能が足りずに速度が落ちているようです。
K3V2 は Vivante GC4000 による描画が崩れて正しく表示されませんでした。
ログを見る限りアプリケーション自体は動いているようです。
● Emscripten のビルド
Emscripten のビルドは gcc/clang の代わりに emcc コマンドを用います。
obj (.o) の代わりが .bc (bitcode) です。
emcc file1.cpp -o file1.bc
実際に実行できるよう JavaScript に変換 (ld/link) するには下記のようにします。
emcc file1.bc -o file1.js
または
emcc file1.bc -o file1.html
実行形式は js だけの場合と、html 含めたブラウザ向けの 2種類あります。
ローカルで実行する場合は node コマンド (Node.js) を使うことが可能で、
この場合は js だけで OK です。
WebGL の描画や preload 指定した追加ファイルを読み込む場合は html で出力し、
Web サーバー経由でブラウザから読み込みます。
実行形式 実行環境 バンドル ----------------------------------------------------- .js node --embed-file .html Browser --emded-file or --preload-file
● 実行手順の例
ローカルで実行する場合 (node)
emcc file1.cpp -o file1.bc emcc file2.cpp -o file2.bc emcc file1.bc file2.bc -o file.js node file.js
ローカルサーバーを経由する場合 (Browser)
emcc file1.cpp -o file1.bc emcc file2.cpp -o file2.bc emcc file1.bc file2.bc -o file.html python -m SimpleHTTPServer 8888 ブラウザで http://localhost:8888/file.html を開く
● ファイルシステム
Emscripten の実行環境は仮想 FileSystem を持っており、
内部的に Unix FileSystem をエミュレートします。
実行時に読み込むファイル群は、一旦この仮想 FileSystem 内に読み込んでおく必要があります。
必要なファイルを実行ファイルに埋め込む方法は下記 2種類あります。
--preload-file 外部ファイル(*.data)にアーカイブし起動時に読み込む --embed-file js に埋め込む
–embed-file の例
emcc file1.cpp -o file1.bc emcc file2.cpp -o file2.bc emcc file1.bc file2.bc -o file.js --embed-file root/shaders
↑この場合 root/shaders フォルダ以下のファイルをすべて js の中に埋め込みます。
仮想 FileSystem 内のパスも /root/shaders/* とみなします。
もし実際のデータ置き場と、仮想 FileSystem 内のパスが異なる場合は
‘@’ マークを使います。
emcc file1.cpp -o file1.bc emcc file2.cpp -o file2.bc emcc file1.bc file2.bc -o file.js --embed-file root/shaders@/data/shaders
↑ ‘@’ 以降が内部の仮想パスの指定になります。
実際のデータは root/shaders 以下に存在しており、
実行時は /data/shaders にあるとみなされます。
–embed-file は間違いが少なく node でも利用できて便利なのですが、
ファイル数が増えるとビルドが極端に遅くなる問題があります。
バンドルが 200MB くらいあるプロジェクトではコマンドが返ってきませんでした。
–preload-file の場合はデータを外部ファイルにまとめるため、
データ容量が増えても比較的時間がかからずにビルドできます。
emcc file1.cpp -o file1.bc emcc file2.cpp -o file2.bc emcc file1.bc file2.bc -o file.html --embed-file root/shaders@/data/shaders python -m SimpleHTTPServer 8888 ブラウザで http://localhost:8888/file.html を開く
どちらにせよ、これらの方法はブラウザを開いたあと長いロードが入るので
その間何もできなくなります。
現実的には、動的な逐次読み込みを実現する必要があるでしょう。
またメモリ上の仮想 FileSystem はデータの保存ができません。
必要ならば Indexed Databased を FileSystem に mount して
利用することができるようです。
● Inline JavaScript
仮想マシンが JavaScript となる Emscripten では、Inline Assembler ではなく
Inline JavaScript を利用することができます。
#include
~
int main()
{
EM_ASM(
~
JavaScript code
);
return 0;
}
EM_ASM() の中に JavaScript code を記述します。
仮想ファイルシステムへの動的な読み込みなど色々コードを埋め込むことができるようです。
● Main Loop
Emscripten では callback を使って Game の Main Loop の代わりにします。
例えば AppModule::Render() を毎フレーム呼び出したい場合は下記のような使い方になります。
#include
class AppModule {
public:
void Render();
};
// 毎フレーム呼ばれる
static void ems_loop( void* arg )
{
AppModule* iApp= reinterpret_cast( arg );
iApp->Render();
}
int main()
{
AppModule* iApp= new AppModule();
// callback の登録
emscripten_set_main_loop_arg( ems_loop, iApp, 0, TRUE );
delete iApp;
return 0;
}
● HeapSize
実行環境のメモリが足りずに、アプリケーションを起動できないことがあります。
下記のようにアプリケーションが使用する HEAP SIZE を指定することができます。
emcc file.cpp -o file.bc emcc file.bc -o file.html -s TOTAL_MEMORY=134217728
あまり大きな値を指定し過ぎると、今度はブラウザ側のメモリが足りず
Out of Memory でロードが止まってしまうことがあるようです。
● まとめ
・Android Cortex-A15/A9 + Firefox は遅くなかった
・Emscripten のビルドと実行手順
・仮想ファイルシステムとバンドル
・MainLoop と HeapSize
次回 : Emscripten C++/OpenGL ES 2.0 のアプリケーションをブラウザで動かす (3)
関連エントリ
・Emscripten C++/OpenGL ES 2.0 のアプリケーションをブラウザで動かす (1)
・Emscripten C++/OpenGL ES 2.0 のアプリケーションをブラウザで動かす 一覧