32KiBをフレームバッファにしたときのサイズ感を考える会
以前32KiBの フレームバッファ無し の描画について考えた( https://zenn.dev/okuoku/scraps/79c24bd4ea2982 )けど、営業上の要求からどうしてもフレームバッファにしたい事情が出てきたのでフレームバッファ化を検討することにする。
320x240
基本解像度である320x240で考えると、32KiB / (320x240) = 約 3.4 bpp(bits per pixel) 。つまり1ピクセルあたり2bitとか3bitなら収まることになる。 ...ちょっとゲーム的には厳しいもんがあるかな。。これは非サポートで良いと思う。
分割描画
LVGLのように、分割して描画することを考える。16bpp で32KiBに収めるとすると、51ラインまでなら保持できるようなので、キリの良いところで、 320 x 48 x16 bpp あたりは妥当な仕様だろう。
ただし、分割描画をする場合 RaspberryPi Picoをサポートできない という割と致命的な問題がある。。
シングルバッファ化
現状の分割では64KiBの描画データバジェットをダブルバッファする前提で描画データを32KiBに絞っている。
原理的にはシングルバッファ化することでバジェットを64KiBに倍増でき、その場合は4bpp(16色)を達成できてギリギリゲームに使えるかなという感じになる。例えばPico-8が128x128の16色画面となっている。
160x120
単純な 1/2 解像度にすることで、必要なメモリは 1/4 になる。この場合、 32KiB / (160x120) = 13.7 bpp 。つまり8bpp(いわゆる256色)なら運用可能なサイズと言える。
一旦コレを基準解像度にしようかなぁ。。いわゆるMakeCode arcadeハードウェアも少々大きい 160x128 ではあるが同様の仕様でサポートできる。
ちなみにゲームボーイやゲームギアの 160x144 も同様に収められる。
シングルバッファ化すべきか
描画処理の実施中にデータが書き換えられたとしても、基本的にはティアリングが現われるだけで困らないのでシングルバッファ化は妥当な気もする。フレームバッファ不要スタイルの描画APIでは、描画コマンドを処理中に上書きされるのは危険なのでどうしてもダブルバッファが必要になるが。。
仮にシングルバッファ化する場合、ゲームに32KiBのメモリを拠出させる方法を考える必要がある。 ...32KiBも連続するんなら適当にアドレスだけOSに渡すスタイルでも良いかな。。つまり、
- OSから32KiBのフレームバッファ用メモリを取得できる低解像度モード
- OSに32KiBの追加フレームバッファを拠出する必要がある高解像度モード
の2種を用意し、ゲーム側で適宜切り替えさせることになる。320x240x16色モードには64KiBのストレージは必要なものの、それ自体は連続している必要性はない。ただし、RaspberryPi Picoのことを考えると、それらは同時に存在する必要がある。