🐄

2021年の思い出コーナー

2021/12/29に公開

総評

学びの多い1年だった気がする。自分の得意技に篭らないのが重要だったというか何と言うか。

本業の方はちょっと前では信じられないくらい、 具体的には賞与だけで自分の入社2年目の年俸レベル という国内の事業所としては異次元の厚遇になった。今後しばらくは会社的にイベントが無いので流石に1/2〜3/4になると思うけど。立場上は日本語で言うと"主任"になったけど部下とか居ないのであんまし。。

本業以外の活動は公開できて集中的にやるもの(Yuniframe)の進捗が割とあった。公開しない方(ゲーム製作その他)は一進一退という感じでちょっとやりざまを再考する必要を感じている。

今年のヒット賞

今年は記事書きに時間を振れなかった。それでも 385 B! は過去最高。

https://b.hatena.ne.jp/entry/s/zenn.dev/okuoku/articles/e12f39e5c669cc

https://b.hatena.ne.jp/entry/s/zenn.dev/okuoku/articles/bc57255d35dfad

Appleの〜 はもっとハッキングやビジネスモデルを中心にブラックに書く案もあったけど、さわやか風に振った。クリックされるテクニックだね。個人的にはここ数年 Appleの直近の目標は人間にカメラかレーダーを付けること だと考えていて、そこに対する道筋としてのセキュリティという風に書いた方が当たりは大きくなったんじゃないかという気はする。まぁその辺の感じかたは人それぞれで予測が付かないので、記事での扱いはかなりコンパクトにした。

自分のプロジェクトの記事が入ってないじゃんというツッコミは有るかもしれないが、 そもそも3ケタもブックマークを集めるようなものは他人がやるべき だと考えているのでその辺は予定通りと言える。いいアイデアも最初は小さくしか受けないもので、受けた人数規模はアイデアの質に比例するものではないと思う。すごくいいアイデアは最初からマスに受けるがそういうものはそもそも事業化すべきだろう。

プロジェクト進捗

Yuniframeにかなり時間的経済的に投資した。というか表立ったものは全部Yuniframeの活動の一環と言える。

WebAssemblyなゲームを自前のプラットフォーム(Yuniframe)で動かす

現段階で、Duktape + wasm2c + C-WebGL でUnityが動いている。

https://zenn.dev/okuoku/articles/5a7a04e75234b3

https://zenn.dev/okuoku/articles/9276f1bc71fc70

2021年に入った段階では、Node.js上でWebAssemblyもJavaScriptも動かしていたことを考えるとそれなりの進捗だと思う。法的な事情で最終的なパッケージャーは公開していない。

これ 最初のチャレンジではJSDomを使って割とDOMと真面目に向きあっていた が、Unityほどの規模のコードでもDOMは適当で良いということがわかって 実際死ぬほど適当なWrapper でもなんとかなっている。

これと殆ど同じ手法でGoのアプリをNintendo Switchに移植した事例も出てきたが、あちらはGo側の工夫でこのアプローチを捨てたようだ。

https://zenn.dev/hajimehoshi/articles/72f027db464280

この記事に挙がっている、"コンパイルが遅い" と "マルチスレッドでない" はYuniframeでも問題になるだろう。前者はこちらの工夫でどうにでもなるが、後者はそもそもUnity WebGLの作りがかなり荒く、直近では解決のしようが無い気がする。

Yuniframe

そもそもYuniframeって何だよという話がなかなか着地していないが、現状は:

  • 超ポータブルなCでゲームアプリを書く仕組み

と要約することにしている。

何故ポータブルなのか? それはYuniframeのデザインが一切のsystem callを排して 単一の呼出し規約であるNCCC void func(const uint64_t* in, uint64_t* out) だけ [1] でOS/プラットフォームとやりとりできるようにしたため。関数の呼出しはCコンパイラのある環境ならどこでもでき、OS/プラットフォーム固有の構造体は存在しないので、ヘッダの互換性問題もない。...現実にはWindowsとLinuxでさえ呼出し規約自体に互換性が無いのでこの特徴を活用しずらいが、WebAssemblyのように単一の呼出し規約をユニバーサルに使うところでは強力な特徴になる。

そんなの構造体や関数シグネチャを uint64_t の配列に置きかえただけじゃんという声もあるかもしれないが、ミニマリズムを突きつめることで生まれるアプリケーション構成法が有るんじゃないかという気がしている。UNIX思想。

実際、何でも.jsonにすることでWebAPIの世界は飛躍的に進化したように見える。超大昔からASN.1なりXMLなりが存在したのに、進化には.jsonが必要だった。言い換えると、.jsonのパーサはどこにでも存在するが、ASN.1やXMLはそれに比べて ほんのちょっとだけ 扱いが面倒だったことが進化を妨げていたのではないか。同様に、アプリケーションがOS間で移植されるために必要なコストを文字通りのゼロにするのがYuniframeの思想と言える。例えば、POSIXは割とポータブルだがOS間の移植の手間はゼロにはならない。

(ビッグエンディアンなCPUの存在はWebAssembly同様意図的に無視している。)

もちろん、HTTPが2以降バイナリプロトコルになったり、様々な分野でProtocolBuffersの採用が増えているように複雑で面倒なバイナリへの揺り戻しも常に発生している。ただ、この分野でYuniframeのような単純化で成功したものは過去にあまり例が無く、WebAssembly向けの同様なプロジェクトであるWASIは(セキュリティ都合で)複雑な方に振っているという現実がある。

で、Yuniframeは 根性で ↑ のようにWebGLなゲームを移植できる程度の機能セットを(SDL2上に)実現している。Webアプリの構造 -- つまり、1枚ゲーム画面を描画する という機能だけでゲームを作成させる -- は、Yuniframeのような必要最低限の機能のみを実装したいケースで非常に相性が良かった。このWebアプリの構造をネイティブアプリの構築に流用することを、ReactNativeとは違った側面で(再)発見したのがYuniframeのポイントだろう。

C-WebGL

WebGL1のC言語版である C-WebGL はVulkanバックエンドで絵が出るところまで実装できた。

https://twitter.com/okuoku/status/1427234852483440642

C-WebGLは今のところ Yuniframeのプロトタイプリポジトリに混ぜてある が、どこかのタイミングでスピンアウトさせたいと考え中。実装は4段階でやっていて:

  1. システムのOpenGL ES実装にパススルーする実装 (gles2)
  2. OpenGL ES2の実装が処理できるステートを全部トラッキングするだけの実装 (tracker)
  3. tracker を使用して描画指示のタイミングでシステムのOpenGL ESをtrackerの設定内容に合わせて描画する実装 (tgles2)
  4. tracker を使用してVulkanで描画を実施する実装 (vulkan)

のような段階を踏んでいる。ポイントは このどの段階でもUnity WebGLが動作する という点で、単純なテストではカバーできない複雑なユースケースが存在するGPUライブラリにとっては、かなり有利な状況で実装を進めることができた。

例えば、Vulkanの仕様に理解できない点がある場合、 gles2 実装をVulkanで(ANGLEを使って)動かして比較する ことで"お手本"を得ることができる。

近年のGPU APIの構成方法はステートレスが基本になっている。OpenGLでは 線の太さ といったパラメタがシステム上のステートとして表現されるが、それを tracker モジュールでGPUと 独立して記録できる ようにし、GPUバックエンドの実装負担を下げる設計になっている。(MesaやANGLEも同様の実装方針を採っている)

ちょっと開発機を別のことに使ってしまっていて最近は進捗が無いが、DX11バックエンドは完成させたいところ。。(Xboxで使うのに便利だから -- 現状のXbox実装 はANGLEなので巨大で取り回しが悪い)

現状のC-WebGLはUnity WebGLに必要な部分しか実装していないため、ブラウザで通常WebGLを実装するのに使用されているANGLEよりもずっとコンパクトになっている。ANGLEはOpenGL ES3.2をほぼ完全に実装しているため非常に巨大なライブラリになっている。

将来的には、SafariがWebGL2に対応してしまったのでC-WebGLもWebGL2の事を考えないといけないんだけどなかなか進んでいない。。あと、 逆に、WebGLをOpenGL1の固定パイプラインで実行できないか というのも考えている。実際、単にWebブラウズしているだけならプログラマブルパイプラインの大半は使っていないのでGPUの電源をかなり積極的に切れるんじゃないかというのがあって、現在のOpenGL2で書かれたコンポジションを逆にCPUでセキュアに実行しやすい形に丸める方法が必要という予想がある。

Mini-XR, C-Fetch, ...

その他、各種Web platform APIsの標準化状況を調査して、C言語APIにできないかの調査を色々やった。いくつかはscrapに書いたけど、現状全く記事にできていない。

Web platformが漁場として優れているのは、各社のOS/プラットフォーム間の差異を調べて共通部分を取る作業が事前に行われているため。SDKの設計作業の大半はこの部分に費されるので、そこをアウトソースできるのは非常に大きい。

ただ調査は進んでるけど、C-WebGLのように既存のアプリを動かして検証するという手法が取れないのでどうしたもんか。。

来年

来年はロングショットな計画が着地し始める年になる...と期待したい。

乾電池駆動のスマホおもちゃが作れないか(マイコン向けYuniframe)

https://zenn.dev/okuoku/scraps/815d555243b6a4

たまには "理由は説明できないけど兎に角クールだと思う" プロジェクト をやらないとアーキテクトとしての筋力が維持できない面があって、今はテーマとしてこれを選んでいる。

(本業の方では大企業特有の層の厚さがあってアーキテクトをやれるほどの実力に到達していないってのも有るけど -- 他の人がやっちゃうので)

子ども向けのおもちゃで高いやつになると 抵抗膜タッチパネル + カラー液晶 + QRコードが読めるカメラ = 9,680円 というスペックになるので、このレベルのフォームファクタで"スマホおもちゃ"を作るとどういうスペックとアーキテクチャになるのかを自分なりに考えてみたい。

... が、カメラを接続できるマイコンが実は非常にレアで難易度が高い。今のところ、 Maix Amigoを使って基礎部分の実験をしている けど、コレは RISC-V 64bit 2コア + 8MiB RAM というかなり非現実的なスペックで、もうちょっとスペックの低いSony SpresenseかESP32あたりにしたい。いやまぁ 北米のたまごっちピクスが 8MiB RAM ではあるけど。。

現状は、センサとかを付けて歩きまわってスペックの追い込みをしている。

https://twitter.com/okuoku/status/1469987324004298756

スマホは身近でありながらそのアーキテクチャの特殊性(画面切っても裏で動いている、アプリケーションの画面とOSの画面を合成して表示する必要がある 等)はあまり意識されない傾向があって、その辺を意識して数MiBのRAMに収めると面白いのではないだろうか。Webブラウザのような接続必須のアプリは別にクラウドで良いんだし。

脚注
  1. 実際にはstrict aliasing ruleに反するので union に変更する予定 ↩︎

Discussion