2D描画系(その4)

上記の実装で試してみたところ、PC上ではCPUの爆速に支えられて何の問題もなかったが、Android実機にもっていったところ結構重かった。描画時にマトリクスを「キューに詰める」という動作は一回につきfloat値x9個のメモリコピー動作であり、さすがにまずかった。

…ということで、やはり当初構想していた「最大32個分のuniformバッファ上に描画マトリクスを持ち、オブジェクトはポインタでそこを参照して描画用の値を書き込む」路線に変更。不規則にobjectの生成/破棄を繰り返すと歯抜けになってGPU的には非効率になるが、CPUレベルでは毎フレームメモリコピーを発生させないため、トータルの速度は上がると判断。


uniformバッファインスタンスは、それを使用しているオブジェクトが存在している限り残り続け、使用しているオブジェクトが一つもなくなれば破棄される仕組み。新たに生成する際は先に「空きのある」バッファを探し、そこの隙間に突っ込むので、最初に大量のオブジェクトを生成して不規則に破棄すると歯抜けになりやすいが、生成/破棄を繰り返すような場合ではそれほど問題にはなるまい。


今のところテストスクリプトが2Dと3Dのタスクを同時に動かしているので、どちらがどの程度重いか、というのは一度ベンチマークを取って見なければならんわな。3Dテスト用に出してる円筒も、一本当たりが600ポリゴンぐらいなので、5本出していると約3000ポリゴンといったところか。分割数を4倍にしても(トータル12000ポリゴン)大して変わらない速度で動いていたので、GPUの能力的にはまだまだ余裕がありそうな感じ。重くなるとしたらCPU側の最適化に失敗している場合、ということになるだろう。まあ、シェーダに大したことやらせてないというのもあるけども。


WikipediaでNexus7(2012)のTegra3を調べたら「GeForce6相当」との記述があったのだけども、GeForce6の発表は2004年頃なので、字面通り解釈すれば約10年前のPC相当の描画性能はあるということに。ゲーム機だと年代的にはPS2が主流でまだPS3が出る前ぐらいだな。なので、描画周りの仕様規模的には当時ぐらいを想定しておけばよいのかもしれない。