Direct3D 11에서 장치 제거 시나리오 처리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.

InstructionsInstructions

1단계:Step 1:

렌더링 루프에서 장치 제거 오류에 대 한 검사를 포함 합니다.Include a check for the device removed error in the rendering loop. Idxgiswapchain::P 재전송 (또는 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 오류 코드 중 하나를 반환 합니다.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. 이 오류가 한 번 이라도 발생 하면 코드에서 장치 제거 조건이 발생 하 여 디버깅 해야 함을 의미 합니다.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 래스터화 Platform) 를 사용 하 고 있고 하드웨어 어댑터를 사용할 수 있게 되 면이 오류 코드가 반환 될 수 있습니다.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

자세한 내용은 GetDeviceRemovedReasonDXGI _ ERROR를 참조 하세요.For more details, see GetDeviceRemovedReason and DXGI_ERROR.

장치 제거 처리 테스트Testing Device Removed Handling

Visual Studio의 개발자 명령 프롬프트는 Visual Studio 그래픽 진단와 관련 된 Direct3D 이벤트 캡처 및 재생에 대 한 명령줄 도구 ' dxcap.exe '를 지원 합니다.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.exe 및 해당 지원 Dll은 더 이상 Windows SDK를 통해 배포 되지 않는 Windows 10 용 그래픽 도구의 일부로 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