Sdílet prostřednictvím


Řešení scénářů odebrání zařízení v Direct3D 11

Toto téma vysvětluje, jak znovu vytvořit řetěz rozhraní zařízení Direct3D a DXGI při odebrání nebo opětovné inicializaci grafického adaptéru.

V Rozhraní DirectX 9 můžou aplikace narazit na stav "ztraceného zařízení", kdy zařízení D3D přejde do nefunkčního stavu. Například když aplikace Direct3D 9 na celé obrazovce ztratí zaměření, zařízení Direct3D se stane "ztraceným"; všechny pokusy o kreslení, pokud je zařízení ztracené, tichým selháním selžou. Direct3D 11 používá rozhraní virtuálních grafických zařízení, což umožňuje více programům sdílet stejné fyzické grafické zařízení a eliminovat podmínky, kdy aplikace ztratí kontrolu nad zařízením Direct3D. Dostupnost grafického adaptéru se ale stále může změnit. Například:

  • Ovladač grafiky je upgradován.
  • Systém se změní z grafického adaptéru s úsporou výkonu na grafický adaptér výkonu.
  • Grafické zařízení přestane reagovat a resetuje se.
  • Grafický adaptér je fyzicky připojený nebo odebraný.

V případě výskytu takových okolností vrátí DXGI kód chyby označující, že zařízení Direct3D musí být znovu inicializováno a prostředky zařízení musí být znovu vytvořeny. Tento názorný postup vysvětluje, jak můžou aplikace a hry Direct3D 11 rozpoznat a reagovat na všechny okolnosti, kdy se grafický adaptér resetuje, odebere nebo změní. Příklady kódu jsou k dispozici ze šablony aplikace DirectX 11 (Universal Windows) poskytované v sadě Microsoft Visual Studio 2015.

Instrukce

Krok 1:

Do smyčky vykreslování zahrňte kontrolu odstraněné chyby zařízení. Představte snímek voláním IDXGISwapChain::Present (nebo Present1atd.). Potom zkontrolujte, jestli se vrátil DXGI_ERROR_DEVICE_REMOVED nebo DXGI_ERROR_DEVICE_RESET.

Nejprve šablona ukládá HRESULT vrácené řetězcem swapování DXGI.

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

Poté, co se postaráte o všechnu další práci spojenou s prezentací rámce, šablona zkontroluje chybu odstranění zařízení. V případě potřeby volá metodu, která zpracuje stav odebrání zařízení:

// 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);
}

Krok 2:

Při reagování na změny velikosti okna také zahrňte kontrolu chyby odebrání zařízení. Toto je dobré místo, kde můžete zkontrolovat DXGI_ERROR_DEVICE_REMOVED nebo DXGI_ERROR_DEVICE_RESET z několika důvodů:

  • Změna velikosti řetězce swapů vyžaduje volání základního adaptéru DXGI, který může vrátit chybu odstranění zařízení.
  • Aplikace se možná přesunula na monitor, který je připojený k jinému grafickému zařízení.
  • Při odebrání nebo resetování grafického zařízení se rozlišení plochy často změní, což vede ke změně velikosti okna.

Šablona zkontroluje HRESULT vrácenou 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);
}

Krok 3:

Kdykoli vaše aplikace obdrží chybu DXGI_ERROR_DEVICE_REMOVED, musí znovu inicializovat zařízení Direct3D a znovu vytvořit všechny prostředky závislé na zařízení. Uvolněte veškeré reference na prostředky grafického zařízení vytvořené s předchozím zařízením Direct3D; tyto prostředky jsou nyní neplatné a všechny reference na swap chain musí být uvolněny, než může být vytvořen nový.

Metoda HandleDeviceLost uvolní swap řetězec a upozorní komponenty aplikace na potřebu uvolnění prostředků zařízení.

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();
}

Pak vytvoří nový swap chain a znovu inicializuje prostředky závislé na zařízení, které jsou řízeny třídou správy zařízení.

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

Po opětovném vytvoření zařízení a swap chain informuje komponenty aplikace, aby znovu inicializovaly prostředky závislé na zařízení.

// 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();
}

Když metoda HandleDeviceLost ukončí, řízení se vrací do vykreslovací smyčky, která pokračuje kreslením dalšího snímku.

Poznámky

Zkoumání příčiny chyb souvisejících s odstraněním zařízení

Opakované problémy s odebranými zařízeními DXGI můžou znamenat, že váš grafický kód vytváří neplatné podmínky během rutiny kreslení. Může také značit selhání hardwaru nebo chybu v grafickém ovladači. Pokud chcete zjistit příčinu chyb způsobených odebráním zařízení, použijte ID3D11Device::GetDeviceRemovedReason před uvolněním zařízení Direct3D. Tato metoda vrátí jeden ze šesti možných kódů chyb DXGI označující důvod chyby odebrané zařízení:

  • DXGI_ERROR_DEVICE_HUNG: Ovladač grafiky přestal reagovat kvůli neplatné kombinaci grafických příkazů odeslaných aplikací. Pokud se tato chyba zobrazí opakovaně, je pravděpodobné, že aplikace způsobila zablokování zařízení a je potřeba ji ladit.
  • DXGI_ERROR_DEVICE_REMOVED: Grafické zařízení bylo fyzicky odebráno, vypnuto nebo došlo k upgradu ovladače. K tomu dochází příležitostně a je to normální; vaše aplikace či hra by měly obnovit prostředky zařízení, jak je popsáno v tomto tématu.
  • DXGI_ERROR_DEVICE_RESET: Grafické zařízení selhalo kvůli špatně vytvořenému příkazu. Pokud se tato chyba zobrazí opakovaně, může to znamenat, že kód odesílá neplatné příkazy kreslení.
  • DXGI_ERROR_DRIVER_INTERNAL_ERROR: Grafický ovladač narazil na chybu a resetoval zařízení.
  • DXGI_ERROR_INVALID_CALL: Aplikace poskytla neplatná data parametrů. Pokud se tato chyba zobrazí i jednou, znamená to, že váš kód způsobil stav s odebraným zařízením a musí být laděn.
  • S_OK: Vráceno, když bylo grafické zařízení povoleno, zakázáno nebo resetováno, aniž by došlo ke zneplatnění aktuálního grafického zařízení. Tento kód chyby se může vrátit například v případě, že aplikace používá platformu WARP (Windows Advanced Rasterization Platform) a bude k dispozici hardwarový adaptér.

Následující kód načte kód chyby DXGI_ERROR_DEVICE_REMOVED a vypíše jej do ladicí konzole. Vložte tento kód na začátek metody HandleDeviceLost:

    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

Další podrobnosti najdete v tématu GetDeviceRemovedReason a DXGI_ERROR.

Testování manipulace s odebraným zařízením

Vývojářský příkazový řádek sady Visual Studio podporuje nástroj příkazového řádku dxcap pro zachytávání událostí Direct3D a přehrávání související s diagnostikou grafiky sady Visual Studio. Při spuštění aplikace můžete použít možnost příkazového řádku -forcetdr, která vynutí detekci a obnovení časového limitu GPU, čímž se aktivuje DXGI_ERROR_DEVICE_REMOVED a umožní vám otestovat kód zpracování chyb.

Poznámka DXCap a jeho podpůrné knihovny DLL jsou nainstalovány do system32/syswow64 jako součást Grafických nástrojů pro Windows 10, které již nejsou distribuovány prostřednictvím sady Windows SDK. Místo toho jsou poskytovány prostřednictvím funkce Grafické nástroje na vyžádání, která je volitelná komponenta operačního systému a musí být nainstalována, aby bylo možné povolit a používat grafické nástroje ve Windows 10. Další informace o instalaci grafických nástrojů pro Windows 10 najdete zde: https://msdn.microsoft.com/library/mt125501.aspx#InstallGraphicsTools