Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo argomento illustra come ricreare la catena di interfaccia del dispositivo Direct3D e DXGI quando la scheda grafica viene rimossa o reinizializzata.
In DirectX 9 le applicazioni potrebbero riscontrare una condizione "dispositivo perso" in cui il dispositivo D3D entra in uno stato non operativo. Ad esempio, quando un'applicazione Direct3D 9 a schermo intero perde lo stato attivo, il dispositivo Direct3D diventa "perso;" eventuali tentativi di disegno con un dispositivo perso avranno esito negativo in modo invisibile all'utente. Direct3D 11 usa interfacce dei dispositivi grafici virtuali, consentendo a più programmi di condividere lo stesso dispositivo grafico fisico ed eliminando le condizioni in cui le app perdono il controllo del dispositivo Direct3D. Tuttavia, è comunque possibile che la disponibilità della scheda grafica cambi. Per esempio:
- Il driver grafico viene aggiornato.
- Il sistema passa da una scheda grafica di risparmio energia a una scheda grafica con prestazioni.
- Il dispositivo grafico smette di rispondere e viene reimpostato.
- Una scheda grafica viene fisicamente collegata o scollegata.
Quando si verificano tali circostanze, DXGI restituisce un codice di errore che indica che il dispositivo Direct3D deve essere reinizializzato e le risorse del dispositivo devono essere ricreate. Questa procedura dettagliata illustra in che modo app e giochi Direct3D 11 possono rilevare e rispondere a qualsiasi circostanza in cui la scheda grafica viene reimpostata, rimossa o modificata. Gli esempi di codice vengono forniti dal modello App DirectX 11 (Windows universale) fornito con Microsoft Visual Studio 2015.
Disposizioni
Passaggio 1:
Includere un controllo della presenza dell'errore di rimozione del dispositivo nel ciclo di rendering. Presentare il frame chiamando IDXGISwapChain::Present (o Present1, e così via). Controllare quindi se è stato restituito DXGI_ERROR_DEVICE_REMOVED o DXGI_ERROR_DEVICE_RESET.
In primo luogo, il modello archivia il valore HRESULT restituito dalla catena di scambio DXGI:
HRESULT hr = m_swapChain->Present(1, 0);
Dopo aver eseguito tutte le altre operazioni per la presentazione del frame, il modello verifica la presenza dell'errore di rimozione del dispositivo. Se necessario, chiama un metodo per gestire la condizione di rimozione del dispositivo.
// 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);
}
Passaggio 2:
Includere anche un controllo per l'errore di rimozione del dispositivo quando si risponde alle modifiche delle dimensioni della finestra. Questo è un buon posto per verificare la presenza di DXGI_ERROR_DEVICE_REMOVED o DXGI_ERROR_DEVICE_RESET per diversi motivi:
- Il ridimensionamento della catena di scambio richiede una chiamata all'adattatore DXGI sottostante, che può restituire l'errore di dispositivo rimosso.
- L'app potrebbe essere stata spostata in un monitor collegato a un dispositivo grafico diverso.
- Quando un dispositivo grafico viene rimosso o reimpostato, la risoluzione del desktop cambia spesso, determinando una modifica delle dimensioni della finestra.
Il modello controlla il valore HRESULT restituito da 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);
}
Passaggio 3:
Ogni volta che l'app riceve l'errore di DXGI_ERROR_DEVICE_REMOVED, deve reinizializzare il dispositivo Direct3D e ricreare tutte le risorse dipendenti dal dispositivo. Rilasciare tutti i riferimenti alle risorse del dispositivo grafico create con il dispositivo Direct3D precedente; tali risorse sono ora non valide e tutti i riferimenti alla catena di scambio devono essere rilasciati prima di crearne uno nuovo.
Il metodo HandleDeviceLost rilascia la catena di scambio e notifica ai componenti dell'app di rilasciare le risorse del dispositivo:
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();
}
Crea quindi una nuova catena di scambio e reinizializza le risorse dipendenti dal dispositivo controllate dalla classe di gestione dei dispositivi:
// Create the new device and swap chain.
CreateDeviceResources();
m_d2dContext->SetDpi(m_dpi, m_dpi);
CreateWindowSizeDependentResources();
Dopo aver ristabilito il dispositivo e la catena di scambio, notifica ai componenti dell'app di reinizializzare le risorse dipendenti dal dispositivo:
// 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();
}
Quando il metodo HandleDeviceLost viene chiuso, il controllo torna al ciclo di rendering, che continua a disegnare il fotogramma successivo.
Osservazioni:
Analisi della causa degli errori di rimozione del dispositivo
Problemi ricorrenti con errori di rimozione del dispositivo DXGI possono indicare che il tuo codice grafico sta creando condizioni non valide durante una routine di disegno. Può anche indicare un errore hardware o un bug nel driver grafico. Per analizzare la causa degli errori relativi alla rimozione del dispositivo, chiamare ID3D11Device::GetDeviceRemovedReason prima di rilasciare il dispositivo Direct3D. Questo metodo restituisce uno dei sei codici di errore DXGI possibili che indicano il motivo dell'errore di rimozione del dispositivo:
- DXGI_ERROR_DEVICE_HUNG: il driver grafico ha smesso di rispondere a causa di una combinazione non valida di comandi grafici inviati dall'app. Se si verifica ripetutamente questo errore, è probabile che l'app abbia causato il blocco del dispositivo e che sia necessario eseguire il debug.
- DXGI_ERROR_DEVICE_REMOVED: il dispositivo grafico è stato rimosso fisicamente, disattivato o si è verificato un aggiornamento del driver. Questo accade occasionalmente ed è normale; l'app o il gioco devono ricreare le risorse del dispositivo come descritto in questo argomento.
- DXGI_ERROR_DEVICE_RESET: Il dispositivo grafico ha fallito a causa di un comando malformato. Se viene visualizzato ripetutamente questo errore, il codice potrebbe inviare comandi di disegno non validi.
- DXGI_ERROR_DRIVER_INTERNAL_ERROR: il driver grafico ha rilevato un errore e reimpostato il dispositivo.
- DXGI_ERROR_INVALID_CALL: L'applicazione ha fornito dati di parametro non validi. Se viene visualizzato questo errore anche una volta, significa che il codice ha causato la condizione di rimozione del dispositivo e deve essere eseguito il debug.
- S_OK: restituito quando un dispositivo grafico è stato abilitato, disabilitato o reimpostato senza invalidare il dispositivo grafico corrente. Ad esempio, questo codice di errore può essere restituito se un'app utilizza Windows Advanced Rasterization Platform (WARP) e quando una scheda hardware diventa disponibile.
Il codice seguente recupererà il codice di errore DXGI_ERROR_DEVICE_REMOVED e lo stamperà nella console di debug. Inserire questo codice all'inizio del metodo 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
Per altri dettagli, vedere GetDeviceRemovedReason e DXGI_ERROR.
Gestione della rimozione del dispositivo di test
Il prompt dei comandi per gli sviluppatori di Visual Studio supporta uno strumento da riga di comando "dxcap" per l'acquisizione e la riproduzione di eventi Direct3D correlati alla diagnostica grafica di Visual Studio. È possibile usare l'opzione della riga di comando "-forcetdr" mentre l'app è in esecuzione, il che forza un evento di rilevamento e ripristino del timeout GPU, attivando così DXGI_ERROR_DEVICE_REMOVED e consentendo di testare il codice di gestione degli errori.
Nota DXCap e le DLL di supporto vengono installate in system32/syswow64 come parte degli strumenti di grafica per Windows 10 che non sono più distribuiti tramite Windows SDK. Al contrario, vengono forniti tramite la funzionalità Strumenti grafici su richiesta che è un componente del sistema operativo facoltativo e deve essere installato per abilitare e usare gli strumenti di grafica in Windows 10. Altre informazioni su come installare gli strumenti di grafica per Windows 10 sono disponibili qui: https://msdn.microsoft.com/library/mt125501.aspx#InstallGraphicsTools