LAB

プログラムTIPS最適化Tips

研究室プログラムTIPS2013.11.28

4x4行列の省メモリ高速化のアイデア

ちょうど一年前に4x4行列の「行優先」と「列優先」の違いの話をしました。
以前は「列優先」のほうが内積演算を生成できるメリットがあることを紹介しました。

では具体的にそれ以外でもっと便利なことはないのか?
というわけで今回は「メモリ・レジスタ節約」について紹介します。

ゲーム内でよく利用するスキニングボーンアニメーションがあります。
これは基本的には

1.回転(Rotate)
2.拡大縮小(Scale)
3.平行移動量(Translate)

の3つの要素で表すことが多いです。これを四元数(Quaternion)で持っておき、その回転要素と残りの要素を取り込んだものとして最終的に4×4行列に変換して使用することが一般的です。

4×4行列とは次のようなデータ構造です。

2009-04-06_00.PNG

GPU内部では行列もベクトルデータとして扱われ、「4要素ベクトルが4本」として扱われます。
レジスタの本数はハードウェアが持っている有限個数のリソースです。これを節約できれば、より沢山の行列を同時に読み込むことができるようになります。
この場合「行優先」で考えると成分の位置は次のようになります。

2009-04-06_01.PNG

モーションアニメーションのデータは上記の「回転」「拡大/縮小」「平行移動」3つの要素のみで構成されますので、基本的には「回転3×3行列」と「平行移動3要素ベクトル」のみで情報量は足りることになります。
そこでデータを減らして4×3行列にしてみます。

2009-04-06_02.PNG

このようにW成分は必要ないわけですが、レジスタは1本あたりXYZWで4要素あります。
W成分を使わなくなっただけではレジスタの本数が減りません。
これでは節約の効果はありませんよね。

さらにここで「転置(Transpose)」を使います。
すると、次のようになります。

2009-04-06_03.PNG

どうでしょうか。データがぴったり詰まってレジスタが一本節約できました!
この状態では転置されていますので「列優先」の状態です。
行優先の4×3行列列優先の3×4行列にすることがアニメーションデータの節約になることがわかります。
ちなみにOpenGLではこの「列優先」のデータ構造が採用されています。

たとえばGPUが256本のレジスタを持っていたとすると、その中に設定できる4×4行列の数は

256÷4本 =64個

になりますが、これが列優先の3×4行列ならば

256÷3本 =85個

の行列パレットを登録することができるようになります。
これを応用してさらに節約して回転をクォータニオン、平行移動量を3要素ベクトル、拡大率をW値に持つことでさらに2本のベクトルにまで節約することもできます。
そうすればなんと128個・・・つまり4×4行列の倍の姿勢データを持つことができるようになります!!

上記は一例にすぎませんが、このように応用の幅が広がっていきます。
最近ではPCのメモリ容量も2GBを超えることが当たり前になっていますが、資源は有限です!
容量を節約することで高速化、時間を短縮することで高速化。
ゲーム制作の現場では快適なゲーム作品にするためにスタッフが常に努力をしています。
遊んでくれるユーザーに少しでも快適な操作感・レスポンスで楽しんでほしい、ゲームプログラマのコード高速化にはそんな思いがあります。

ヘキサドライブは常にプレイしてくれる皆さんのことを考えています。

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE