Low-latency frame syncing モードは、ゲーム・レンダリング・RHI の各スレッドと GPU 間で行われるスレッド同期の方式を変更することによって、操作入力の遅延を大幅に軽減します。これまでのエンジンのリリースでは、ゲーム スレッドはフレームの最後でレンダリング スレッドと同期していました。r.OneFrameThreadLag コンソール変数が有効化されると (デフォルトでは有効化されています)、ゲーム スレッドがレンダリング スレッドよりも完全に 1 フレーム分先に進むことはなくなります。 概して、プラットフォーム固有のグラフィックス ドライバーは、Present() を呼び出すスレッドをストールさせることによって、フレームの描画よりも速くゲームが進むのを防ぎます。ドライバーは、スワップチェーンが満たされるようにし、空きがなくなると呼び出したスレッドをストールします。UE4 の並行レンダリング処理が導入される前は、この同期の動作で正しかったのです。ゲーム スレッドがレンダリング スレッドを待ち、さらに、グラフィックス ドライバー/OS によってストールが実行されるのですから。しかしながら、並行レンダリングの導入にともなって、Present() を呼び出すスレッドは RHI スレッドになったため、ドライバーによって調節されるスレッドになりましたゲーム スレッドはレンダリング スレッドとのみ引き続き同期します。そのことによって、これらの両スレッドは、GPU およびフリップされるフレームよりも以前よりも数段先に進むことができるようになります。そしてこれにより、rhi.SyncInterval を 2 に設定した 30hz のタイトルでは、ワーストケースで最大 130 ms の入力遅延が発生する可能性が出てきたのです。
UE4 の並行レンダリング以前と同じ入力遅延にするには、今度はゲームスレッドと RHI スレッドを同期させる必要があります。Vsync を有効にしている場合は、スワップチェーンから一定で予測可能な同期のインターバルが得られます (言い換えるならば、スワップチェーンによってフロントバッファ/バックバッファが切り替えられる時が分かります)。ゲーム スレッドのフレーム開始を、Vsync を基準としてそこから任意の時点に同期させることによって、入力遅延を正確にコントロールすることが可能になるのです。この時点を慎重に選択することによって、入力遅延と引き換えにパフォーマンスを得ることができます (あるいは、その逆が可能です)。
この新たな低遅延フレーム同期のモードでは、r.GTSyncType (ゲーム スレッド同期のタイプ) という新たなコンソール変数が加わりました。このコンソール変数によって、新たな同期メカニズムの動作が決まります。この変数は以下のような値をとります。
値 | 説明 |
---|---|
0 | ゲーム スレッドがレンダリング スレッドと同期します。(古い動作であり、デフォルトの設定) |
1 | ゲーム スレッドが RHI スレッドと同期します。 (UE4 の並行レンダリング以前の動作に相当する) |
2 | ゲーム スレッドが、現在のスワップチェーン ±オフセット (単位: ミリ秒) と同期します。 |
モード 2 の同期を行うためにエンジンは、Present() が呼び出された時にドライバーに渡されるインデックスで示されるフレームをトラッキングします。このインデックスは、各フレームが切り替わる正確な時を示すプラットフォームのフレーム切り替え統計値から得ることができます。これらの値を利用して、次のフレーム切り替えがいつになるのか予測することができ、さらに、その時間に基づいてゲーム スレッドの次のフレームを開始させることができます。
rhi.SyncSlackMS コンソール変数は、次に予測される vsync 時間に適用するオフセットを制御するために使います。この値を小さくすると、エンジンのパイプラインを短くすることと引き換えに入力遅延が短縮され、処理落ちによってコマ落ちが起こりやすくなります。反対に、値を大きくすると、エンジンのパイプラインが延伸して、入力遅延の増加と引き換えにタイトルには処理落ちに対する耐性がつきます。
通常、この新たなフレーム同期システムを使うタイトルでは、許容できるフレームレートを維持しつつ、できるだけ rhi.SyncSlackMS を小さくするようにするべきです。
たとえば、30hz のタイトルのために次のようにコンソール変数を設定します。
- rhi.SyncInterval 2
- r.GTSyncType 2
- r.OneFrameThreadLag 1
- r.Vsync 1
- rhi.SyncSlackMS 0
入力遅延はベストケースで最大 66ms (30hz のフレームの 2 倍の長さ) となります。rhi.SyncSlackMS を 10 に増やすと、入力遅延はベストケースで最大 76ms になるはずです。
r.GTSyncType 2 は 60hz のタイトルにも有効ですが (すなわち rhi.SyncInterval を 1 に設定)、その利便性は目立たなくなります。30hz に比較して 2 倍のフレームレートになり、入力遅延が半減するからです。
未サポートのプラットフォームでは r.GTSyncType 2 が有効にならず、モード 1 になります。
0