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

多くの場合、このウィンドウに続けて、Unreal Engine クラッシュ レポータ ウィンドウが表示されます。
画像をクリックするとフルサイズで表示されます。
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 のクラッシュは、以下のような様々な理由で発生します。
- メモリ不足 (OOM)
- 高負荷な処理中のタイムアウト (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 および TdrDdiDelay を作成します。
-
TdrDelay
はタイムアウトのしきい値を設定します。これは、プロセッシングとメモリ (VRAM) を処理する GPU スケジューラからの割り込み要求を GPU が遅延させる秒数です。 -
TdrDdiDelay
は、オペレーティング システム (OS) がドライバーから離れることをスレッドに対して許可する時間を設定します。設定した時間が経過すると、タイムアウト遅延エラーが発生します。
レジストリ キーについて詳細については、Microsoft の Tdr レジストリ キー に関するドキュメントを参照してください。
Windows オペレーティング システムのレジストリ キーを変更すると、予期しない結果になり、Windows の完全な再インストールが必要になる場合があります。このチュートリアルに記載されているレジストリ キーの追加または編集により、そういった結果になるわけではありませんが、作業を進める前にシステムのバックアップを作成することをお勧めします。Epic Games では、システム レジストリの変更によってシステムに生じたいかなる損害に対しても、一切責任を負いません。
グラフィック ドライバーに 2 つのレジストリ キーを追加する必要があります。レジストリ キーを追加するには、次の手順を実行します。
-
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。Windows オペレーティング システムの検索バーに「run」と入力します。Run (ファイル名を指定して実行) アプリケーションを開きます。
画像をクリックするとフルサイズで表示されます。
-
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。検索フィールドに「regedit」と入力します。[OK] をクリックして、レジストリ編集ツールを開きます。
画像をクリックするとフルサイズで表示されます。
-
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。レジストリ編集ツールの左側にあるナビゲーションの GraphicsDrivers セクションに移動します。この場所は、
Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers
です。画像をクリックするとフルサイズで表示されます。
レジストリ キーは「GraphicsDrivers」フォルダに追加する必要があります。その子フォルダではりません。正しいフォルダを選択していることを確認します。
-
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。必要なレジストリ キーは、
TdrDelay
という名称です。このレジストリ キーがすでに存在する場合は、ダブルクリックして編集します。まだない場合は、右側のペインで右クリックして、[New (新規)] > [DWORD (32-bit) Value (DWORD (32 ビット) 値)] を選択します。 -
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。[Base (表記)] を [Decimal (10 進数)] に設定します。TdrDelay の [Value (値のデータ)] を「60」に設定します。[OK] をクリックして終了します。
-
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。
TdrDdiDelay
という 2 つ目のレジストリ キーが必要です。このレジストリがすでに存在する場合は、ダブルクリックして編集します。まだない場合は、右側のペインで右クリックし、[New (新規)] > [DWORD (32-bit) Value (DWORD (32 ビット) 値)] を選択して作成します。 -
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。[Base (表記)] を [Decimal (10 進数)] に設定します。TdrDdiDelay` の [Value (値のデータ)] を「60」に設定します。[OK] をクリックして終了します。
-
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。レジストリに
TdrDelay
およびTdrDdiDelay
の両方が含まれていることを確認します。画像をクリックするとフルサイズで表示されます。
-
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。レジストリ エディタを閉じます。
-
Unreal Engine 統合を組織の新しいソフトウェアとして追加します。これらの変更を反映させるためにコンピュータを再起動します。
これらのレジストリ キーを追加したことで、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 のバージョンを確認できます。