GPU クラッシュの概要
グラフィックを多用するプロジェクトでは、GPU クラッシュが発生する可能性があります。GPU クラッシュが発生すると、次のようなウィンドウが表示されます。

多くの場合、このウィンドウに続けて、Unreal Engine の [Crash Reporter (クラッシュ レポータ)] ウィンドウが表示されます。
クリックしてフルサイズで表示。
GPU クラッシュが発生する理由
Windows では、プロセスの処理完了までの時間が長すぎるといった理由で、過剰にメモリが使用されたことによるアプリケーションのロックを防ぐためのセーフガードが実装されています。このような状況では、Windows は GPU ドライバーを強制終了して、アプリケーションをクラッシュさせます。
GPU クラッシュが発生すると、コールスタックとログに「GPUCrash - exiting due to D3D device being lost - D3D Hung」や「DXGI_ERROR_DEVICE_REMOVED with Reason:DXGI_ERROR_DEVICE_HUNG」などのメッセージが表示される場合があります。
GPU クラッシュは、さまざまな理由で発生します。下記はその例です。
- メモリ不足 (out of memory)
- 負荷の重い操作の実行中のタイムアウト (TDR イベント)
- エンジン コードのバグ
- ドライバのバグ
- オペレーティング システムのバグ
- ハードウェアの問題
こうした理由から、Unreal Engine のようなアプリケーションでは、クラッシュが発生する理由を常に把握することができません。したがって、アプリケーション レベルでクラッシュを回避することが不可能な場合もあります。 以下のセクションでは、根本原因の特定に役立ついくつかのデバッグ オプションと、実行可能ないくつかの予防策をご紹介します。
GPU クラッシュをデバッグする
Unreal Engine でクラッシュが発生した場合、クラッシュ レポータとログ ファイルによって生成されたコールスタックで、何が起こっているかを理解するのに役立つ情報が記載されていないかどうかを調べると思います。しかしながら、GPU クラッシュが発生した場合、CPU コールスタックではクラッシュの本当の原因が分かりません。ここには、GPU クラッシュが発生したときに CPU が何をしていたかの情報のみが記載されるためです。つまり、実用的な情報は提供されません。
次の 2 つのデバッグ コマンド ライン引数を使用すると、有用な情報を含むログを出力できます。
-gpucrashdebugging
は GPU の進行状況を収集し、GPU クラッシュのデバッグ時に現在の GPU の状態を追跡します。-d3ddebug
は、D3D パイプラインに関する情報を提供します。
これらのコマンド ライン引数を一緒に使用しないことを強くお勧めします。ログを生成するには、各フラグを個別に指定してエンジンを実行する必要があります。
これらの各コマンド ラインでエンジンを実行した後にクラッシュが発生した場合、ログは「[自分のプロジェクト]/Saved/Logs」フォルダに保存されます。
Windows でアプリケーションがクラッシュすると、クラッシュの診断にも役立つダンプ ファイルが生成されます。これらの詳細については、Visual Studio デバッガーでダンプ ファイルを使用する方法 を説明している Microsoft の Visual Studio ドキュメント を参照してください。
GPU のメモリ不足 (OOM) の問題を解決する
GPU のメモリが不足すると、クラッシュが発生する可能性があります。クラッシュが発生するかどうかは、使用されている RHI に大きく依存します。一部は他のものより復帰しやすく、OOM イベントの場合でもクラッシュせず動作が遅くなるだけの場合もあります。
Windows タスク マネージャー の [Performance (パフォーマンス)] タブを開くと、メモリ不足のクラッシュが発生する理由を把握できます。ここで、GPU を選択し (1)、その使用可能なメモリと現在消費している量を確認できます (2)。

使用可能なメモリと現在の消費量を含む、GPU の現在の統計を表示する Windows タスク マネージャー。
プロジェクトを開いて実行すると、使用可能な GPU メモリと消費されている GPU メモリの量を確認できます。使用可能なメモリの制限に近づいている場合、クラッシュの原因はそれである可能性が最も高いです。この場合、次のことを試してください。
- 大量の GPU メモリを消費している可能性がある他のプログラムを閉じる。
- 低解像度のテクスチャ、低解像度のメッシュ、シーン内のオブジェクトを減らすカリングなどを使用してシーンを単純化する。
- 低い画面解像度を使用する。
- エディタで作業している間は、レベル ビューポートの [Screen Percentage (スクリーン比率)] を使用すると、より低い解像度でレンダリングできます。
- エディタでの作業中に複数のビューポートを開いている場合、1 つを残してすべて閉じる。
- Niagara やレイ トレーシングなどの主要な機能を無効にしない。
- これらのコンポーネントをバイパスすると、多くのことが変更されます。それにより、GPU クラッシュの原因を誤解してしまう可能性があります。
コストのかかる操作 (TDR イベント) によって発生する GPU のタイムアウトについて
CPU が何かを計算するために GPU にコマンドを送信すると、CPU はタイマーを設定して、GPU が操作を完了するのに必要な時間をカウントします。CPU が操作に時間がかかると判断した場合 (デフォルトでは、Windows では 2 秒)、ドライバがリセットされ、GPU クラッシュが発生します。これは、TDR イベント (またはタイムアウト検出および回復) と呼ばれます。
TDR イベントをトリガーするような量の作業をエンジンが GPU に送信しないようにするのが理想的です。代わりに、エンジンがタスクを小さなチャンクに分割して、TDR を回避できるような状態にする必要があります。これらのタイプのイベントを回避するには、Windows レジストリを編集して、タイムアウトが発生するまでの時間を長くします (「TDR イベントを解決する方法」については、以下の手順を参照してください)。
レイ トレーシングによる TDR イベント
ハードウェア レイ トレーシング はとりわけ負荷が重く、有効にすると TDR イベントをトリガーする可能性が高くなります。一部の高負荷なレイ トレーシング パス (非常に高い解像度でのレイ トレーシング グローバル イルミネーションなど) は、レンダリングに時間がかかり、TDR イベントをトリガーする可能性があります。
最も負荷の重いレイ トレーシング パス (グローバル イルミネーションと反射) では、次のコンソール変数を使用して、単一のパスではなくタイルでパスをレンダリングできます。
r.RayTracing.GlobalIllumination.RenderTileSize
r.RayTracing.Reflections.RenderTileSize
パスのタイル サイズが 0 より大きい場合、これらのパスは N x N ピクセル タイルでレンダリングされ、各タイルは個別の GPU コマンド バッファとして送信されます。これにより、タイムアウト検出をトリガーすることなく、高品質のレンダリングが可能になります。
TDR イベントを解決する方法
TDR イベントを回避する 1 つの方法として、Windows レジストリ キーを編集して、Windows が TDR イベントをトリガーするまでに必要な時間を増やすことがあります。このガイドでは、2 つの新しいレジストリ キー、TdrDelay および TdrDiDelay を作成します。
-
TdrDelay
はタイムアウトのしきい値を設定します。これは、プロセッシングとメモリ (VRAM) を処理する GPU スケジューラからの割り込み要求を GPU が遅延させる秒数です。 -
TdrDdiDelay
は、オペレーティング システム (OS) がドライバから離れることをスレッドに対して許可する時間を設定します。設定した時間が経過すると、タイムアウト遅延エラーが発生します。
レジストリ キーの詳細については、Tdr レジストリ キー に関する Microsoft のドキュメントを参照してください。
Windows オペレーティング システムのレジストリ キーを変更すると、予期しない結果になり、Windows の完全な再インストールが必要になる場合があります。このチュートリアルに記載されているレジストリ キーの追加または編集により、そういった結果になるわけではありませんが、作業を進める前にシステムのバックアップを作成することをお勧めします。Epic Games では、システム レジストリの変更によってシステムに生じたいかなる損害に対しても、一切責任を負いません。
グラフィック ドライバに 2 つのレジストリ キーを追加する必要があります。レジストリ キーを追加するには、次の手順を実行します。
-
Windows オペレーティング システムの検索バーに「run」と入力します。Run アプリケーションを開きます。
クリックしてフルサイズで表示。
-
検索フィールドに「regedit」と入力します。[OK] をクリックして、レジストリ編集ツールを開きます。
クリックしてフルサイズで表示。
-
レジストリ編集ツールの左側にあるナビゲーションの [GraphicsDrivers] セクションに移動します。これの場所は
Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers
です。クリックしてフルサイズで表示。
レジストリ キーは「GraphicsDrivers」フォルダに追加する必要があります。その子フォルダではありません。正しいフォルダを選択していることを確認します。
-
必要なレジストリ キーは、
TdrDelay
という名称です。このレジストリ キーがすでに存在する場合は、ダブルクリックして編集します。まだない場合は、右側のペインで右クリックして、[New (新規)] > [DWORD (32-bit) Value (DWORD (32 ビット) 値)] を選択します。 -
[Base (基数)] を [Decimal (10 進数)] に設定します。[TdrDelay] の [Value (値)] を「60」に設定します。[OK] をクリックして終了します。
-
TdrDdiDelay
という 2 つ目のレジストリ キーが必要です。このレジストリがすでに存在する場合は、ダブルクリックして編集します。まだない場合は、右側のペインで右クリックし、[New (新規)] > [DWORD (32-bit) Value (DWORD (32 ビット) 値)] を選択して作成します。 -
[Base (基数)] を [Decimal (10 進数)] に設定します。
TdrDdiDelay
の [Value (値)] を「60」に設定します。[OK] をクリックして終了します。 -
レジストリに
TdrDelay
およびTdrDdiDelay
の両方が含まれていることを確認します。クリックしてフルサイズで表示。
-
レジストリ エディタを閉じます。
-
これらの変更を反映させるためにコンピュータを再起動します。
これらのレジストリ キーを追加したことで、Windows は、アプリケーションのプロセスに時間がかかりすぎていると判断するまで、60 秒間待機するようになります。
これはレンダリングに起因する GPU クラッシュを抑える適切な方法であるものの、これですべてのクラッシュが解決されるわけではありません。一度に非常に多くのデータを処理しようとすると、タイムアウト遅延をどんなに長く設定しても、GPU がタイムアウトする可能性があります。この解決策は、グラフィック カードに若干の追加時間を提供することのみを目的としています。
エンジン コード、ドライバ、およびオペレーティング システムのバグを調査する
エンジン コード、ドライバ、またはオペレーティング システムのバグも、GPU クラッシュの原因となる可能性があります。OOM および TDR イベントが根本原因ではないことが分かった場合、次はこれらが GPU クラッシュの原因となっているかどうかを調査するのが一般的です。
-gpucrashdebugging
と-d3ddebug
を使用してエンジンを実行します (前述のように個別に行います)。-onethread
と-forcerhibypass
を使用してエンジンを実行し、エンジンを強制的に 1 つのスレッドのみで実行します。これは、根本的な問題がスレッド化 / タイミングの問題であるかどうかを判断するのに役立ちます。r.RDG.Debug=1
でエンジンを実行して、適切に設定されていないレンダー パスに関する情報を取得します。r.RDG.ImmediateMode=1
でエンジンを実行し、作成直後にパスを実行するために Render Dependence Graph (RDG) を強制します。これにより、より意味のあるコールスタックを得られます。これにより他のものも変更されるため、クラッシュの原因を誤解する可能性があることに注意してください。とはいえ、それでも調査する価値はあります。- 別の RHI に切り替えます。たとえば、DirectX 12 (DX12) を使用している場合は、DirectX 11 (DX11) に切り替えることができます。そのうちの 1 つでのみクラッシュが発生した場合は、問題のレベルが高いか低いかを特定するのに役立ちます。一部の機能は特定の RHI でのみ動作することに注意してください (たとえば、ハードウェア レイ トレーシングは DX12 でのみサポートされています)。
- シーンに A/B テストを使用します。
- レンダリング パスのオンとオフを切り替えて、クラッシュが発生するかどうかを確認します。多くの場合、誤ったパスによって問題が発生します。こうした類のチェックを行うことで、発生していることに関する良い手がかりを得ることができます。
- Lumen、Nanite、レイ トレーシングなどのレンダリング機能をオンまたはオフにします。これらのうち一部は、システムの再起動が必要になる場合があることに注意してください。
- シーン内の特定のオブジェクトを非表示 / 表示します。これにより、問題が特定のアセットに関連しているかどうかを特定できます。
GPU クラッシュが特定のドライバに関するものかどうかを調べる場合、上記のすべての情報が当てはまり、利用可能な最新のドライバも入手する必要があります。また、このドライバが引き起こす可能性のある既知の問題について、製造元に確認することもできます。
GPU クラッシュがオペレーティング システムに関するものかどうかを調べる場合、上記のすべての情報が当てはまります。また、Windows の場合は、バージョン 20H2 を使用することを強くお勧めします。Windows キーを押して「winver」と入力すると、使用している Windows のバージョンを確認できます。