Gestion des scénarios de suppression de périphériques dans Direct3D 11

Applies to Windows and Windows Phone

Cette rubrique explique comment recréer la chaîne d’interface de périphériques Direct3D et DXGI quand la carte graphique est supprimée ou réinitialisée.

Dans DirectX 9, les applications peuvent avoir un état de type « périphérique perdu », quand un périphérique D3D passe à un état non opérationnel. Par exemple, quand une application Direct3D 9 en mode plein écran perd le focus, le périphérique Direct3D est « perdu ». Toute tentative de dessin avec un périphérique perdu entraîne un échec sans avertissement. Direct3D 11 utilise des interfaces GDI (Graphics Device Interface) virtuelles, ce qui permet à plusieurs programmes de partager le même périphérique graphique physique et d’éviter les situations où les applications perdent le contrôle du périphérique Direct3D. Cependant, la disponibilité de la carte graphique peut toujours changer. Par exemple :

  • Le pilote graphique est mis à jour.
  • Le système passe d’une carte graphique axée sur l’économie d’énergie à une carte graphique axée sur les performances.
  • Le périphérique graphique cesse de répondre et est réinitialisé.
  • Une carte graphique est attachée ou supprimée physiquement.

Dans ces circonstances, DXGI retourne un code d’erreur indiquant que le périphérique Direct3D doit être réinitialisé et que les ressources de périphérique doivent être recréées. Cette procédure pas à pas montre comment les applications et les jeux Direct3D 11 peuvent détecter ces situations et réagir de manière appropriée quand la carte graphique est réinitialisée, supprimée ou modifiée. Des exemples de code sont fournis à partir des modèles d’applications Direct3D du Windows Store inclus dans Microsoft Visual Studio 2013.

Instructions

Étape 1:

Incluez une recherche de l’erreur relative à une suppression de périphérique dans la boucle de rendu. Présentez l’image en appelant IDXGISwapChain::Present (ou Present1, etc.). Vérifiez ensuite si DXGI_ERROR_DEVICE_REMOVED est retourné.

Tout d’abord, le modèle stocke le HRESULT retourné par la chaîne de permutation DXGI :



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

Après avoir géré les autres travaux de présentation de l’image, le modèle vérifie s’il existe une erreur relative à la suppression de périphérique. Si nécessaire, il appelle une méthode pour gérer l’état de suppression du périphérique :



// 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)
{
    HandleDeviceLost();
}
else
{
    DX::ThrowIfFailed(hr);
}

Étape 2:

Incluez également une recherche de l’erreur relative à une suppression de périphérique en réponse aux changements de taille de fenêtre. Il s’agit d’un emplacement approprié pour rechercher DXGI_ERROR_DEVICE_REMOVED, pour plusieurs raisons :

  • Le redimensionnement de la chaîne de permutation nécessite un appel à l’adaptateur DXGI sous-jacent, ce qui peut retourner l’erreur relative à une suppression de périphérique.
  • L’application peut avoir été déplacée vers un moniteur attaché à un autre périphérique graphique.
  • Quand un périphérique graphique est supprimé ou réinitialisé, la résolution du Bureau change le plus souvent, ce qui entraîne un changement de taille de fenêtre pour les applications de bureau et les applications du Windows Store en mode plein écran.

Le modèle vérifie le HRESULT retourné par 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)
{
    // 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);
}

Étape 3:

Chaque fois que votre application reçoit l’erreur DXGI_ERROR_DEVICE_REMOVED, elle doit réinitialiser le périphérique Direct3D, ainsi que les ressources dépendantes du périphérique. Libérez les références aux ressources de périphérique graphique créées avec le précédent périphérique Direct3D. Ces ressources ne sont plus valides. Toutes les références à la chaîne de permutation doivent être libérées pour permettre la création d’une autre chaîne.

La méthode HandleDeviceLost libère la chaîne de permutation et indique aux composants d’application de libérer les ressources de périphérique :


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

Elle crée ensuite une chaîne de permutation, puis réinitialise les ressources dépendantes du périphérique contrôlées par la classe de gestion de périphérique :


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

Une fois que le périphérique et la chaîne de permutation ont été rétablis, elle indique aux composants d’application de réinitialiser les ressources dépendantes du périphérique :


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

À la fin de la méthode HandleDeviceLost, le contrôle retourne à la boucle de rendu, qui continue de dessiner l’image suivante.

Remarques

Recherche de l’origine des erreurs relatives à une suppression de périphérique

La répétition d’erreurs relatives à une suppression de périphérique DXGI peut indiquer que votre code graphique crée des conditions non valides durant une routine de dessin. Elle peut également indiquer une défaillance matérielle ou un bogue dans le pilote graphique. Pour rechercher l’origine des erreurs relatives à une suppression de périphérique, appelez ID3D11Device::GetDeviceRemovedReason avant de libérer le périphérique Direct3D. Cette méthode retourne l’un des six codes d’erreur DXGI possibles qui indiquent l’origine de l’erreur relative à une suppression de périphérique :

  • DXGI_ERROR_DEVICE_HUNG : le pilote graphique a cessé de répondre à la suite de l’envoi par l’application d’une combinaison non valide de commandes graphiques. Si vous obtenez cette erreur à plusieurs reprises, cela indique que votre application est probablement à l’origine de la défaillance du périphérique et qu’elle doit être déboguée.
  • DXGI_ERROR_DEVICE_REMOVED : le périphérique graphique a été physiquement enlevé ou désactivé, ou une mise à jour du pilote s’est produite. Cela arrive parfois et c’est une situation normale. Votre application ou votre jeu doit recréer les ressources de périphérique, comme cela est décrit dans cette rubrique.
  • DXGI_ERROR_DEVICE_RESET : une commande mal formulée a entraîné l’échec du périphérique graphique. Si vous obtenez cette erreur à plusieurs reprises, cela peut signifier que votre code envoie des commandes de dessin non valides.
  • DXGI_ERROR_DRIVER_INTERNAL_ERROR : le pilote graphique a rencontré une erreur et a réinitialisé le périphérique.
  • DXGI_ERROR_INVALID_CALL : l’application a fourni des données de paramètres non valides. Si vous obtenez cette erreur, même une seule fois, cela signifie que votre code est à l’origine de l’état de suppression du périphérique et qu’il doit être débogué.
  • S_OK : retourné quand un périphérique graphique a été activé, désactivé ou réinitialisé sans invalider le périphérique graphique actuel. Par exemple, ce code d’erreur peut être retourné si une application utilise WARP (Windows Advanced Rasterization Platform) et si un adaptateur matériel est disponible.

Le code suivant permet de récupérer le code d’erreur DXGI_ERROR_DEVICE_REMOVED et de l’afficher sur la console de débogage. Insérez ce code au début de la méthode 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

Pour plus d’informations, voir GetDeviceRemovedReason et DXGI_ERROR.

 

 

Afficher:
© 2014 Microsoft