純規の暇人趣味ブログ

広くて浅い知識の湖

[DirectX]Aeroの3フレーム遅延とSetMaximumFrameLatency

      HimaJyun

おめでたい事に、(開発者にとっては)にっくきWindowXPがご臨終、時期にVistaも後を追って滅してくれる……

お陰様で新しい機能が使えるのだが……時にはその新しい機能が余計な悪影響を及ぼす事もある。

そう、Vistaから追加されたAeroが3フレームの描画遅延を引き起こすのだ、と言う訳でこれを無効にする方法を……

グラボの設定を変える

この記事は開発者向けに……なんだけども、このタイトルだと一般人(プレイヤー)の一本釣りを達成してしまうかも知れないので、先にそれらの方向けにドライバの設定で無効にする方法も紹介しておく。

for GeForce

Radeonのやり方は知らん、私はGeForceしか持っていないんだ、カネが無いからね。

まずはNVIDIAコントロールパネルを開く、開き方が分からない?デスクトップを右クリックして「NVIDIAコントロールパネル」を選択だ!!
directx-setmaximumframelatency-001

3D設定の管理に進み、グローバル設定から「レンダリング前最大フレーム数」を「1」にする。
directx-setmaximumframelatency-002

後は「適用」
directx-setmaximumframelatency-003

ゲーム(プログラム)別にも設定可能

設定可能、と言うかそうした方が良いかも、先ほどのやり方ではコンピュータ全体の設定が変わってしまうから。

タブを「プログラム設定」に切り替えれば特定のプログラムだけ別の設定を適用する事が出来る。(「追加」を押せばリストにないゲームも追加可能)
directx-setmaximumframelatency-004

リアルタイム性が要求されるFPSとかだけ1にする、とかで良い(もっとも、FPSなんかは既に1に変更するプログラムが仕込まれているだろうが)

例えば東方紅魔郷とか妖々夢とかの「リアルタイム性が要求されるけど、それらを1にする様なプログラムにはなってなさそう」みたいなゲームには良いかも。

プログラム側から変更する

こちらが本文、要は自分の作っているDirectX製ゲームからこれらを操作して1にしてしまおう、と言う訳。

SetMaximumFrameLatency

SetMaximumFrameLatencyメソッドでこの描画遅延をどれくらいにするか変更出来る。

以下の様な感じ

Direct3DCreate9Ex(D3D_SDK_VERSION, &direct3d);
direct3d->CreateDeviceEx(
  D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
  D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp,
  NULL, &device3d
)
device3d->SetMaximumFrameLatency(1);

IDirect3D9Exが持つSetMaximumFrameLatencyを使う。

DirectX8では無理(今更これを使って開発している奴はいない)、DirectX9でも無理、DirectX9EXである必要がある。

9EXはVistaから追加された物、実質DirectX9.5みたいな感じで、基本的にDirectX9と同じように扱える。(XP非対応だが、サポート切れOSに対応するのは時間の無駄だ)

9EXだとD3DPOOL_MANAGEDが使えなくなるが、代わりにデバイスロストが発生しづらく(フォーカスを失ってもデバイスロストしない)様になっているので問題なし。

DirectX10~はIDXGIDevice1にSetMaximumFrameLatencyがあるのでそちらを使う。

ちなみに0にしてはいけない

どこかで「SetMaximumFrameLatency(0)にして遅延をなくしましょう」みたいに書かれていた気がするので言っておくと、これは0にしてはいけない。

このメソッドに指定出来る引数の数値、IDirect3DDevice9ExのSetMaximumFrameLatencyは1~20で、IDXGIDevice1の方は1~16

0を指定するとデフォルトに戻る、すなわち3を指定した状態と同じ事になって無意味。

 - プログラミング ,