Direct3d11 で削除されたデバイス シナリオを処理します。Handle device removed scenarios in Direct3D 11

このトピックでは、グラフィックス アダプターが削除または再初期化されたときに Direct3D と DXGI デバイス インターフェイス チェーンを再作成する方法について説明します。This topic explains how to recreate the Direct3D and DXGI device interface chain when the graphics adapter is removed or reinitialized.

DirectX 9 では、D3D デバイスが非動作状態になったときに、アプリケーションが "デバイス喪失" 状態に見舞われることがあります。In DirectX 9, applications could encounter a "device lost" condition where the D3D device enters a non-operational state. たとえば、全画面 Direct3D 9 アプリケーションがフォーカスを失うと、Direct3D デバイスは "喪失" 状態になります。喪失したデバイスを使って描画しようとしても、エラー表示なしで失敗します。For example, when a full-screen Direct3D 9 application loses focus, the Direct3D device becomes "lost;" any attempts to draw with a lost device will silently fail. Direct3D 11 では、仮想グラフィックス デバイス インターフェイスを使って、複数のプログラムが同一の物理グラフィックス デバイスを共有することができるため、アプリが Direct3D デバイスをコントロールできなくなることはなくなっています。Direct3D 11 uses virtual graphics device interfaces, enabling multiple programs to share the same physical graphics device and eliminating conditions where apps lose control of the Direct3D device. ただし、それでもグラフィックス アダプターが使用できなくなったり、逆に使用できるようになったりすることはありえます。However, it is still possible for graphics adapter availability to change. 次に、例を示します。For example:

  • グラフィックス ドライバーがアップグレードされた場合。The graphics driver is upgraded.
  • システムのグラフィックス アダプターが省電力モードから性能重視モードに変わった場合。The system changes from a power-saving graphics adapter to a performance graphics adapter.
  • グラフィックス デバイスが応答を停止してリセットされた場合。The graphics device stops responding and is reset.
  • グラフィックス アダプターが物理的に接続された場合、または取り外された場合。A graphics adapter is physically attached or removed.

このような状況になると、DXGI はエラー コードを返して、Direct3D デバイスの再起動とデバイス リソースの再作成が必要であることを知らせます。When such circumstances arise, DXGI returns an error code indicating that the Direct3D device must be reinitialized and device resources must be recreated. このチュートリアルでは、グラフィックス アダプターのリセット、削除、変更という事態が生じた場合に、Direct3D 11 アプリとゲームがそれを検出して対応できるようにする方法について説明します。This walkthrough explains how Direct3D 11 apps and games can detect and respond to any circumstance where the graphics adapter is reset, removed, or changed. コード例は、Microsoft Visual Studio 2015 に付属する DirectX 11 アプリ (ユニバーサル Windows) テンプレートから提供されます。Code examples are provided from the DirectX 11 App (Universal Windows) template provided with Microsoft Visual Studio 2015.

手順Instructions

手順 1:Step 1:

レンダリング ループにデバイス削除エラーのチェックを加えます。Include a check for the device removed error in the rendering loop. IDXGISwapChain::Present (または Present1 など) を呼び出して、フレームを表示します。Present the frame by calling IDXGISwapChain::Present (or Present1, and so on). 返されるかどうかを確認し、 DXGI_エラー_デバイス_から削除されたまたはDXGI_エラー_デバイス_リセットします。Then, check whether it returned DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET.

まず、テンプレートは DXGI スワップ チェーンから返された HRESULT を保存します。First, the template stores the HRESULT returned by the DXGI swap chain:

HRESULT hr = m_swapChain->Present(1, 0);

その他のフレーム表示作業の面倒をすべてみた後、テンプレートはデバイス削除エラーをチェックします。After taking care of all other work for presenting the frame, the template checks for the device removed error. 必要な場合は、デバイス削除状態を処理するメソッドを呼び出します。If necessary, it calls a method to handle the device removed condition:

// If the device was removed either by a disconnection or a driver upgrade, we
// must recreate all device resources.
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
{
    HandleDeviceLost();
}
else
{
    DX::ThrowIfFailed(hr);
}

手順 2:Step 2:

また、ウィンドウ サイズの変更に対応する箇所にも、デバイス削除エラーのチェックを加えます。Also, include a check for the device removed error when responding to window size changes. これは、確認するに適して DXGI_エラー_デバイス_から削除されたまたはDXGI_エラー_デバイス_リセットいくつかの理由。This is a good place to check for DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET for several reasons:

  • スワップ チェーンのサイズを変更するには、土台となる DXGI アダプターを呼び出す必要があり、その際にデバイス削除エラーが返される可能性があります。Resizing the swap chain requires a call to the underlying DXGI adapter, which can return the device removed error.
  • 異なるグラフィックス デバイスに接続されたモニターにアプリが移動された可能性があります。The app might have moved to a monitor that's attached to a different graphics device.
  • グラフィックス デバイスが削除またはリセットされると、多くの場合、デスクトップの解像度が変わり、その結果ウィンドウ サイズが変わります。When a graphics device is removed or reset, the desktop resolution often changes, resulting in a window size change.

テンプレートは、ResizeBuffers から返された HRESULT を確認します。The template checks the HRESULT returned by ResizeBuffers:

// If the swap chain already exists, resize it.
HRESULT hr = m_swapChain->ResizeBuffers(
    2, // Double-buffered swap chain.
    static_cast<UINT>(m_d3dRenderTargetSize.Width),
    static_cast<UINT>(m_d3dRenderTargetSize.Height),
    DXGI_FORMAT_B8G8R8A8_UNORM,
    0
    );

if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
{
    // If the device was removed for any reason, a new device and swap chain will need to be created.
    HandleDeviceLost();

    // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method 
    // and correctly set up the new device.
    return;
}
else
{
    DX::ThrowIfFailed(hr);
}

手順 3:Step 3:

アプリが受け取るいつでも、 DXGI_エラー_デバイス_から削除されたエラー、Direct3D デバイスを再初期化し、任意のデバイスに依存を再作成する必要があります、リソース。Any time your app receives the DXGI_ERROR_DEVICE_REMOVED error, it must reinitialize the Direct3D device and recreate any device-dependent resources. 以前の Direct3D デバイスを使って作成したグラフィックス デバイス リソースに対する参照はすべて解放します。このようなリソースは無効になっているため、スワップ チェーンに対する参照はすべて、新しいスワップ チェーンを作成する前に解放する必要があります。Release any references to graphics device resources created with the previous Direct3D device; those resources are now invalid, and all references to the swap chain must be released before a new one can be created.

HandleDeviceLost メソッドは、スワップ チェーンを解放し、アプリ コンポーネントに対してデバイス リソースを解放するよう通知します。The HandleDeviceLost method releases the swap chain and notifies app components to release device resources:

m_swapChain = nullptr;

if (m_deviceNotify != nullptr)
{
    // Notify the renderers that device resources need to be released.
    // This ensures all references to the existing swap chain are released so that a new one can be created.
    m_deviceNotify->OnDeviceLost();
}

続いて、新しいスワップ チェーンを作成し、デバイス管理クラスによって制御されるデバイス依存リソースを再初期化します。Then, it creates a new swap chain and reinitializes the device-dependent resources controlled by the device management class:

// Create the new device and swap chain.
CreateDeviceResources();
m_d2dContext->SetDpi(m_dpi, m_dpi);
CreateWindowSizeDependentResources();

デバイスとスワップ チェーンが再確立された後、アプリ コンポーネントに対してデバイス依存リソースを再初期化するよう通知します。After the device and swap chain have been re-established, it notifies app components to reinitialize device-dependent resources:

// Create the new device and swap chain.
CreateDeviceResources();
m_d2dContext->SetDpi(m_dpi, m_dpi);
CreateWindowSizeDependentResources();

if (m_deviceNotify != nullptr)
{
    // Notify the renderers that resources can now be created again.
    m_deviceNotify->OnDeviceRestored();
}

HandleDeviceLost メソッドが終了すると、制御はレンダリング ループに戻り、処理が続行されて次のフレームが描画されます。When the HandleDeviceLost method exits, control returns to the rendering loop, which continues on to draw the next frame.

注釈Remarks

デバイス削除エラーの原因の調査Investigating the cause of device removed errors

DXGI デバイス削除エラーが繰り返し発生する場合は、アプリケーションのグラフィックス コードが描画ルーチン内で無効な状態を作り出している可能性があります。Repeat issues with DXGI device removed errors can indicate that your graphics code is creating invalid conditions during a drawing routine. また、ハードウェア障害やグラフィックス ドライバーのバグが原因の可能性もあります。It can also indicate a hardware failure or a bug in the graphics driver. デバイス削除エラーの原因を調査するには、Direct3D デバイスを解放する前に ID3D11Device::GetDeviceRemovedReason を呼び出します。To investigate the cause of device removed errors, call ID3D11Device::GetDeviceRemovedReason before releasing the Direct3D device. このメソッドは、デバイス削除エラーの理由を示す 6 種類の DXGI エラー コードの 1 つを返します。This method returns one of six possible DXGI error codes indicating the reason for the device removed error:

  • DXGI_エラー_デバイス_ハング:グラフィック ドライバーは、アプリから送信されたグラフィックス コマンドの無効な組み合わせのため応答を停止します。DXGI_ERROR_DEVICE_HUNG: The graphics driver stopped responding because of an invalid combination of graphics commands sent by the app. このエラーが繰り返し発生する場合は、デバイスがハングする原因はアプリにあり、デバッグの必要があることを示している可能性が高くなります。If you get this error repeatedly, it is a likely indication that your app caused the device to hang and needs to be debugged.
  • DXGI_エラー_デバイス_から削除された:グラフィックス デバイスが物理的に削除された、オフになっているか、ドライバーの更新が発生しました。DXGI_ERROR_DEVICE_REMOVED: The graphics device has been physically removed, turned off, or a driver upgrade has occurred. このエラーはときどき起こることであり、異常ではありません。アプリまたはゲームは、このトピックで説明しているようにデバイス リソースを再作成する必要があります。This happens occasionally and is normal; your app or game should recreate device resources as described in this topic.
  • DXGI_エラー_デバイス_リセット:正しくない形式のコマンドにより、グラフィックス デバイスが失敗しました。DXGI_ERROR_DEVICE_RESET: The graphics device failed because of a badly formed command. このエラーが繰り返し発生する場合は、コードが無効な描画コマンドを送っている可能性があります。If you get this error repeatedly, it may mean that your code is sending invalid drawing commands.
  • DXGI_エラー_ドライバー_内部_エラー:グラフィック ドライバーは、エラーが発生し、デバイスをリセットします。DXGI_ERROR_DRIVER_INTERNAL_ERROR: The graphics driver encountered an error and reset the device.
  • DXGI_エラー_無効な_呼び出す:アプリケーションでは、無効なパラメーターのデータを提供します。DXGI_ERROR_INVALID_CALL: The application provided invalid parameter data. このエラーが 1 回でも発生する場合は、デバイス削除状態の原因がアプリのコードにあり、デバッグの必要があることを意味しています。If you get this error even once, it means that your code caused the device removed condition and must be debugged.
  • S_OK:グラフィックス デバイスが有効になっている、無効になっている、または現在のグラフィックス デバイスを無効にしないリセット時に返されます。S_OK: Returned when a graphics device was enabled, disabled, or reset without invalidating the current graphics device. たとえば、このエラー コードは、アプリが Windows Advanced Rasterization Platform (WARP) を使っていて、ハードウェア アダプターが利用可能になった場合に返されます。For example, this error code can be returned if an app is using Windows Advanced Rasterization Platform (WARP) and a hardware adapter becomes available.

次のコードを取得、 DXGI_エラー_デバイス_から削除されたエラー コードし、デバッグ コンソールに出力します。The following code will retrieve the DXGI_ERROR_DEVICE_REMOVED error code and print it to the debug console. 次のコードを HandleDeviceLost メソッドの先頭に挿入します。Insert this code at the beginning of the HandleDeviceLost method:

    HRESULT reason = m_d3dDevice->GetDeviceRemovedReason();

#if defined(_DEBUG)
    wchar_t outString[100];
    size_t size = 100;
    swprintf_s(outString, size, L"Device removed! DXGI_ERROR code: 0x%X\n", reason);
    OutputDebugStringW(outString);
#endif

詳細については、次を参照してください。 GetDeviceRemovedReason DXGI_エラーします。For more details, see GetDeviceRemovedReason and DXGI_ERROR.

デバイスの削除完了処理のテストTesting Device Removed Handling

Visual Studio の開発者コマンド プロンプトでは、Visual Studio グラフィックス診断に関連する Direct3D イベントのキャプチャと再生を行うコマンド ライン ツール "dxcap" がサポートされます。Visual Studio's Developer Command Prompt supports a command line tool 'dxcap' for Direct3D event capture and playback related to the Visual Studio Graphics Diagnostics. コマンド ライン オプションを使用する"-forcetdr"GPU タイムアウト検出と回復のイベントを強制するアプリを実行中に DXGI がトリガーされました_エラー_デバイス_削除された機能と、エラーをテストすることができますコードを処理します。You can use the command line option "-forcetdr" while your app is running which will force a GPU Timeout Detection and Recovery event, thereby triggering DXGI_ERROR_DEVICE_REMOVED and allowing you to test your error handling code.

DXCap とそのサポート DLL は、Windows 10 向けグラフィックス ツール (Windows SDK では配布されなくなりました) の一部として system32/syswow64 にインストールされます。Note DXCap and its support DLLs are installed into system32/syswow64 as part of the Graphics Tools for Windows 10 which are no longer distributed via the Windows SDK. 代わりに、オプションの OS コンポーネントであるオンデマンドのグラフィックス ツール機能を通じて提供され、Windows 10 でグラフィックス ツールを有効にして使うにはこれをインストールする必要があります。Instead they are provided via the Graphics Tools Feature on Demand that is an optional OS component and must be installed in order to enable and use the Graphics Tools on Windows 10. Windows 10 用グラフィックス ツールをインストールする方法の詳細についてはここにあります。 https://msdn.microsoft.com/library/mt125501.aspx#InstallGraphicsToolsMore information on how to Install the Graphics Tools for Windows 10 can be found here: https://msdn.microsoft.com/library/mt125501.aspx#InstallGraphicsTools