今回は DirectX 9.0 を用いた場合ではどんな感じになるのかを調べてみました。環境は Windows 7 (x64) です。また DirectX 9.0 と表記していますが、実際のところは DirectX 9.0 EX のことを指すものとします。
Windows XP までの頃は VRAM の仮想化というものがなく、デバイスロスト発生のためのケアが必要になっていました。その代わり VRAM にデータを送ってしまい、メインメモリは消費しないということができたように思います。(もしかするとできていなかったのかもしれませんが、今更検証価値も低そうなので手元でテストしていないです・・・。)
一方で Windows 7 になってVRAM仮想化が導入され、VRAMの空き容量など取得が難しくなってきました。 DirectX 9.0 は動くものの、その挙動は XP のころとはまた違ったものになっていると予想されます。それなのに検証をしていないままだったので、 VRAMの情報取得という武器ができた今、調べてみようと思ったわけです。
NVIDIA (Geforce9800) の場合
安定状態になってから頂点バッファ 32MB を D3DPOOL_DEFAULT にて作成しました.
状態 | メモリ(MB) | Dedicate(MB) | 共有メモリ(MB) |
---|---|---|---|
定常状態 | 1054.6 | 47 | 13 |
VertexBuffer作成 1回目 | 1086.7 | 80 | 13 |
VertexBuffer作成 2回目 | 1119.3 | 112 | 13 |
どの場合においてもメインメモリ 32MB 程度消費し、Dedicate のメモリ 32MB ほど消費している結果となりました。
AMD (RADEON) の場合
状態 | メモリ(MB) | Dedicate(MB) | 共有メモリ(MB) |
---|---|---|---|
定常状態 | 1028.9 | 45 | 22 |
VertexBuffer作成 1回目 | 1061.1 | 77 | 22 |
VertexBuffer作成 2回目 | 1093.8 | 109 | 22 |
こちらの場合においてもメインメモリ 32MB 程度消費し、Dedicate のメモリ 32MB ほど消費している結果となりました。
実験その2
描画フレームを回しながら、 100 フレームごとに頂点バッファを確保し描画するという定番のプログラムで実験してみました。
上記の消費メモリが永続的なものではなくテンポラリ扱いならば、相当の数のバッファが作れるはずです。
しかし予想外の結果になりました。
メインメモリの消費が、自分のプロセスに対して発生していました。どうやら D3DPOOL_DEFAULT では自プロセスのどこかにバックアップのバッファが存在するようです。
GTX 750Ti 2GB の状態で普通の 32bit アプリケーションで実行の場合には、x64環境といえども、 1プロセスで使えるサイズは 2GB まで。そのため VRAM 使用量が 1GB 程度のところで DirectX がバッファの作成に失敗しました、とエラーを出しました。このときのプロセスの状況を調べてみましたが、消費されている仮想アドレスが 2GB 近かったです。
一方で、 32bit アプリで LAA オプションをつけて再実行してみると、今度は VRAM 使用量は 1.7GB 程度にまでなり、プロセスの仮想アドレス使用量は 4GB 近くにまでなっていました。
※ このプロセス内での状況を知るのに VMMap というツールは便利です。
まとめ
DirectX 9.0 の場合においては NVIDIA も AMD も同じような挙動となることを確認できました。またどちらの場合においても使用するリソース分、メインメモリも消費していることが確認できました。これはこれで挙動把握さえできてしまえば、扱いやすそうです。
ただ注意が必要であると感じたのが、自分のプロセスの仮想アドレス空間にバックアップ先を確保するため、メモリ不足よりも自身の仮想アドレス空間を枯渇させてしまうのが早そうに思います。 64bit 環境を必須とするなら 32bit アプリケーションの場合、 LAA 必須といってもいいレベルだと思いました。
この場合、よいビデオボードを使っていて 「 4GB の VRAM 全部使いきる DirectX 9.0 アプリケーションを開発してやるぞ。 ただし 32bit アプリケーションだけどなっ」 という夢はかなわないことが判明しました。そんな人は少数派だとは思いますが・・・。