em2native: Xbox(UWP)対応
いやまぁUnityは普通にXbox版があるんでそっち使えよという話ではあるけど。。
(XboxのSDKには普通のゲームSDKとUWP -- Universal Windows Platform の2種類あるが今回は後者を扱う。前者はNDAが必要。)
いわゆるパッケージングが必要なプラットフォームに対応していく。Xbox(UWP) → iOS → Androidの順かな。一度やっておけば、.wasmでバイナリを出すだけで対応できるので色々と便利なはず。
制約
UWPはかなり制約がきつい。
- VisualStudioしか使えない 。このため、一部をclangでビルドしたりするのは工夫が必要。
-
DLLをロードするための
LoadLibrary
が無い 。一応代替APIもあるがコード分けるのが面倒なのでアプリはclangでビルドした静的ライブラリにしたい。 -
ファイルをパッケージに格納する必要がある 。CMakeの場合、なんと
add_executable
にファイルリストを渡し、専用のプロパティVS_DEPLOYMENT_CONTENT
を設定する必要がある。 - あとCMakeが生成する.slnが何か怪しかった気がする。
これらに対応するために、一旦プロジェクトを2つに分ける。
- Emscriptenアプリを 静的ライブラリ.lib とファイルリストの.cmakeに変換するプロジェクト(appプロジェクト)
- ↑のプロジェクトの生成物を取り込んでアプリケーションパッケージを生成するプロジェクト(runtimeプロジェクト)
前者のプロジェクトが wasm2c
を実行し、後者のプロジェクトがYuniframeやDuktape等のランタイム部分をビルドすることになる。
やっぱりビルドに時間が掛かる
とりあえず -ftime-report
すると単なるコード生成だけで20分近く掛かっている。。つまりいわゆるプログラム全体を使った最適化パスは殆ど時間を消費していないので、.c出力を細かく分割してコード生成自体を並列化できるように配慮しない限りなんともならなさそう。
===-------------------------------------------------------------------------===
... Pass execution timing report ...
===-------------------------------------------------------------------------===
Total Execution Time: 4053.4531 seconds (4063.8098 wall clock)
---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name ---
1150.8906 ( 29.7%) 0.2344 ( 0.1%) 1151.1250 ( 28.4%) 1153.5091 ( 28.4%) Simple Register Coalescing
1119.5938 ( 28.9%) 6.3438 ( 3.6%) 1125.9375 ( 27.8%) 1129.2749 ( 27.8%) Machine Instruction Scheduler
619.4688 ( 16.0%) 12.0938 ( 6.9%) 631.5625 ( 15.6%) 634.0365 ( 15.6%) X86 DAG->DAG Instruction Selection
201.9531 ( 5.2%) 127.2188 ( 72.5%) 329.1719 ( 8.1%) 331.4470 ( 8.2%) X86 Assembly Printer
194.8906 ( 5.0%) 2.5625 ( 1.5%) 197.4531 ( 4.9%) 197.7001 ( 4.9%) Greedy Register Allocator
77.9062 ( 2.0%) 0.8281 ( 0.5%) 78.7344 ( 1.9%) 78.4326 ( 1.9%) SROA
31.8125 ( 0.8%) 0.4688 ( 0.3%) 32.2812 ( 0.8%) 32.3988 ( 0.8%) Interprocedural Sparse Conditional Constant Propagation
25.6250 ( 0.7%) 0.1562 ( 0.1%) 25.7812 ( 0.6%) 25.8445 ( 0.6%) Live DEBUG_VALUE analysis
24.2188 ( 0.6%) 0.0469 ( 0.0%) 24.2656 ( 0.6%) 23.9375 ( 0.6%) Combine redundant instructions
23.7812 ( 0.6%) 0.1094 ( 0.1%) 23.8906 ( 0.6%) 23.3037 ( 0.6%) Live Variable Analysis
14.8438 ( 0.4%) 0.0781 ( 0.0%) 14.9219 ( 0.4%) 15.1210 ( 0.4%) CodeGen Prepare
13.9375 ( 0.4%) 0.1406 ( 0.1%) 14.0781 ( 0.3%) 14.4494 ( 0.4%) Combine redundant instructions #3
13.4531 ( 0.3%) 0.3906 ( 0.2%) 13.8438 ( 0.3%) 13.8418 ( 0.3%) Called Value Propagation
11.8281 ( 0.3%) 0.1562 ( 0.1%) 11.9844 ( 0.3%) 12.3254 ( 0.3%) Combine redundant instructions #4
12.3125 ( 0.3%) 0.0938 ( 0.1%) 12.4062 ( 0.3%) 12.2225 ( 0.3%) Combine redundant instructions #2
11.2656 ( 0.3%) 0.2031 ( 0.1%) 11.4688 ( 0.3%) 11.9759 ( 0.3%) Combine redundant instructions #6
10.8125 ( 0.3%) 0.2500 ( 0.1%) 11.0625 ( 0.3%) 10.8868 ( 0.3%) Machine Copy Propagation Pass
9.9375 ( 0.3%) 0.0781 ( 0.0%) 10.0156 ( 0.2%) 9.6331 ( 0.2%) Combine redundant instructions #5
9.2344 ( 0.2%) 0.1406 ( 0.1%) 9.3750 ( 0.2%) 9.5385 ( 0.2%) Live Interval Analysis
9.3906 ( 0.2%) 0.0469 ( 0.0%) 9.4375 ( 0.2%) 9.0803 ( 0.2%) Combine redundant instructions #7
8.7656 ( 0.2%) 0.0312 ( 0.0%) 8.7969 ( 0.2%) 8.6794 ( 0.2%) Loop Strength Reduction
8.3281 ( 0.2%) 0.1094 ( 0.1%) 8.4375 ( 0.2%) 8.3696 ( 0.2%) Machine Common Subexpression Elimination
8.3281 ( 0.2%) 0.1094 ( 0.1%) 8.4375 ( 0.2%) 8.2371 ( 0.2%) Machine Copy Propagation Pass #2
パッケージのファイルはRead-Writeでopenできない
Unityランタイムの起動中にopenに失敗してしまっているようだ。
procmonで見ると ACCESS DENIED
で失敗しているが、これ C++ 的な意味の fstream
はopenに失敗するだけで例外を投げないのでややこしい。。
@@ -37,6 +36,10 @@ file_open_gen(const char* path, yfrm_file_t** file,
p = pth;
}
auto strm = new std::fstream(p, mode | std::ios_base::binary);
+ if(! strm->is_open()){
+ delete strm;
+ return -1;
+ }
auto out = new yfrm_file_t();
out->pth = new fs::path(p);
out->strm = strm;
is_open
でチェックして失敗するようにした。
PCでは動いた
さぁ実機だ。。
Xbox SeriesSでも動いた
PCで動いたものをそのままリモート起動するだけで動作した:
やっぱりUniversalだ!
スタートアップ画像の張り込みとか他のパッケージング作業は後で実装するというかiOSとAndroidとでその辺の仕様がバラバラなのでインターフェースを考えるのが大変。。
サインインしていないと実行できない
(任天堂やSonyのゲーム機と異なり、ChromeOS機のように、)Xboxは本来MSアカウントにサインインしていないと機能しないコンソールなので、1アカウントもデバイスにサインインしていない状態ではアプリケーションが起動しない。
Visual Studioから起動するとちょっとわかりづらいダイアログが出るだけだが、
Windows ストア アプリ 'DB799910-475A-3CAF-98E6-7E47316BAA7C_d7c8pgvss6ysm!App' をアクティブにできません。アクティベーション要求がエラー '操作はサポートされていません。不明なエラー: 0x8004090a' で失敗しました。
実機で直接起動するとちゃんとメッセージが出る: