最近はDX10の話だったので、ちょっと流れをぶち切ってしまいました。
以下の話は、すべてWindowsXP DirectX9での話となります。
Vista以降のDirectX9Exの話はまた異なるため、そのうちにでも。
■ 説明
http://msdn.microsoft.com/ja-jp/library/ee418784%28v=VS.85%29.aspx
このページを見てしまってから思い悩むことになってしまいました。
今までは、以下の方針でリソース作成を行っておけばいいと思っていたのですが。
- 途中で更新するデータである
- → D3DPOOL_DEFAULT + DYNAMIC付き
- 上記以外
- → D3DPOOL_MANAGED
この背景には、D3DPOOL_MANAGEDであればデバイスロスト時の処理が楽になる点と、
実際にはVRAMへ転送済みであるということを想定していたからでした。
しかし、この理解は若干間違っているというのが、図によって分かりました。
- D3DPOOL_DEFAULT
- VRAM上かAGPメモリに配置される
- DYNAMICリソースであればAGPメモリに配置される
- D3DPOOL_MANAGED
- VRAM上かAGPメモリ上、それとシステムメモリにバッキングストアとして配置される
このようになっていることが図から読み取れます。
理解が間違っていたのはD3DPOOL_DEFAULTは常にVRAMと思っていた点でした。
■まとめ
さて、これらの点からどのようにリソースを配置していくべきかを考えてみました。
PC用と想定すれば、実際に動かされる環境はまちまちなので、ドライバに任せる部分は任せて、
多少の動作速度改善に向けた配置を心がけるのが良さそうです。
- 途中で更新するデータ
- 頂点orインデックスバッファなら D3DPOOL_DEFAULT + DYNAMIC付き
- テクスチャなら D3DPOOL_DEFAULT + D3DPOOL_SYSTEMMEMの2重持ち
- SYSTEMMEMに更新したいデータを埋めて、あとで転送する方式にします
- データは最初から終わりまで不変
- D3DPOOL_MANAGEDで配置。
- D3DPOOL_MANAGEDはドライバによって実際に配置される場所が決定される。
- この配置決定には、パフォーマンスや使用状況も考慮されるためお勧めの模様。
注意点としては、上記の動的なデータというのは限りなく少なくしておくべきという点でしょうか。
今回ドキュメントを読んで知ったのですが、MANAGEDとDEFAULTの混在はビデオメモリの断片化を招き、よろしくないとのことです。
DEFAULTを先に作成し終えてから、MANAGEDリソースを作るのが良いとのことです。
もしも対象としている動作環境が VRAM 256MB必須 としてしまい、それ以下の搭載メモリの状況では動作を保証しないというのであれば、
D3DPOOL_MANAGEDを使用する代わりにDEFAULTでもいいのかなと思います。
デバイスロストのときには、データを再度読み込むか、あるいは、SYSTEMMEMで最初から持っておくとかそういうようにして準備する必要はあると思います。
実際にDEFAULT+SYSTEMMEMの両方持っているという状況はOpenGLでは(実装の上では)このようにやっているように見えます。
(メモリの使用状況を見ていると、倍くらい使用メモリが多いので)。