Condividi tramite


Procedura dettagliata: oggetti mancanti a causa dello sfondo Vertex

In questa procedura dettagliata viene illustrato come utilizzare gli strumenti di diagnostica della grafica di Visual Studio per esaminare un oggetto mancante a causa di un errore che si verifica durante la fase di vertex shader.

In questa procedura dettagliata vengono illustrate le attività seguenti:

  • Utilizzo della finestra Elenco eventi grafici per individuare le origini potenziali del problema.

  • Utilizzo della finestra Fasi pipeline grafica per controllare l'effetto delle chiamate all'API di Direct3D DrawIndexed.

  • Utilizzo del Debugger HLSL per esaminare il vertex shader.

  • Utilizzo di Stack di chiamate eventi grafici per individuare l'origine di una costante HLSL errata.

Scenario

Una delle cause più comuni di un oggetto mancante in un'applicazione tridimensionale si verifica quando il vertex shader trasforma i vertici dell'oggetto in un comportamento non corretto o imprevisto, ad esempio l'oggetto può essere ridimensionato in dimensioni molto piccole o è stato trasformato in modo da essere visualizzato dietro la fotocamera, anziché davanti.

In questo scenario, quando l'app viene eseguita a scopo di testing, viene eseguito il rendering dello sfondo come previsto, ma uno degli oggetti non viene visualizzato.Tramite la diagnostica della grafica, è possibile acquisire il problema in un log della grafica in modo da poter eseguire il debug dell'applicazione.Il problema si presenta nel seguente modo nell'app:

Oggetto non visibile.

Analisi

Utilizzando gli strumenti di diagnostica della grafica, è possibile caricare il file di log della grafica per controllare i frame acquisiti durante il test.

Per esaminare un frame nel log di grafica

  1. In Visual Studio caricare un log di grafica contenente un frame che mostra l'oggetto mancante.Verrà visualizzato un nuovo log della grafica in Visual Studio.Nella parte superiore di questa scheda è presente l'output della destinazione di rendering del frame selezionato.Nella parte inferiore è presente Elenco frame che visualizza ogni frame acquisito come immagine di anteprima.

  2. In Elenco frame selezionare un frame che indica che l'oggetto non viene visualizzato.La destinazione rendering viene aggiornata per riflettere il frame selezionato.In questo scenario il log della grafica ha l'aspetto seguente:

    Log grafico in Visual Studio

Dopo avere selezionato un frame in cui viene illustrato il problema, è possibile iniziare a esaminarlo utilizzando l'Elenco eventi grafici.Elenco eventi grafici contiene tutte le chiamate all'API Direct3D effettuate per eseguire il rendering del frame attivo, ad esempio, le chiamate all'API per impostare lo stato del dispositivo, per creare e aggiornare i buffer e per visualizzare oggetti che appaiono nel frame.Molti tipi di chiamate siano interessanti poiché spesso (ma non sempre) si verifica una modifica corrispondente nella destinazione di rendering quando l'applicazione funziona come previsto, ad esempio chiamate di disegno, dispatch, copia o deselezionare.Le chiamate di disegno sono particolarmente interessanti perché ciascuna rappresenta la geometria di cui l'applicazione ha eseguito il rendering (le chiamate di invio possono inoltre eseguire il rendering della geometria).

Poiché si è certi che l'oggetto mancante non è stato disegnato nella destinazione di rendering (in questo caso) (ma che il resto della scena viene disegnato come previsto) è possibile utilizzare Elenco eventi grafici con lo strumento Fasi pipeline grafica per determinare la chiamata di disegno che corrisponde alla geometria mancante dell'oggetto.Nella finestra Fasi pipeline grafica viene mostrata la geometria che è stata inviata a ogni chiamata di disegno, indipendentemente dall'effetto che ha avuto sulla destinazione rendering.Quando ci si sposta nelle chiamate di disegno, le fasi pipeline vengono aggiornate in modo da mostrare la geometria associata alla chiamata e l'output della destinazione di rendering viene aggiornato in modo da visualizzare lo stato della destinazione di rendering dopo aver completato la chiamata.

Per individuare la richiesta di disegno per la geometria mancante

  1. Aprire la finestra Elenco eventi grafici.Sulla barra degli strumenti Diagnostica grafica scegliere Elenco eventi.

  2. Aprire la finestra Fasi pipeline grafica.Sulla barra degli strumenti Diagnostica grafica scegliere Fasi pipeline.

  3. Quando ci si sposta in ogni chiamata di disegno nella finestra Elenco eventi grafici, controllare l'oggetto mancante nella finestra Fasi pipeline grafica.Per semplificare questa procedura, immettere "Disegno" nella casella Cerca posta nell'angolo superiore destro della finestra Elenco eventi grafici.In questo modo l'elenco viene filtrato in modo da contenere solo gli eventi nei cui titoli compare "Disegno".

    Nella finestra Fasi pipeline grafica la fase Assemblaggio input illustra la geometria dell'oggetto prima della trasformazione e la fase Vertex shader mostra lo stesso oggetto dopo che è stato trasformato.In questo scenario, si scoprirà che è stato rilevato l'oggetto mancante quando viene visualizzato nella fase Assemblaggio input, mentre non viene visualizzato nulla nella fase Vertex shader.

    [!NOTA]

    Se altre fasi di geometria, ad esempio Hull Shader, Domain Shader o Geometry Shader, elaborano l'oggetto, potrebbero essere la causa del problema.In genere, il problema è correlato alla primissima fase quando il risultato non viene visualizzato oppure viene visualizzato in modo imprevisto.

  4. Arrestare l'esecuzione quando si raggiunge la chiamata di disegno che corrisponde all'oggetto mancante.In questo scenario, la finestra Fasi pipeline grafica indica che una geometria è stata rilasciata alla GPU (illustrata dell'anteprima di Assemblaggio input), ma non è presente nella destinazione di rendering perché si è verificato un problema durante la fase di vertex shader (indicata dall'anteprima di Vertex shader):

    Evento DrawIndexed e relativo effetto sulla pipeline

Dopo aver per confermato che l'applicazione ha emesso una chiamata di disegno per la geometria mancante dell'oggetto e aver rilevato che il problema si verifica durante la fase di vertex shader, è possibile utilizzare il debugger HLSL per esaminare vertex shader e scoprire cosa è accaduto alla geometria dell'oggetto.È possibile utilizzare il debugger HLSL per esaminare lo stato delle variabili di HLSL durante l'esecuzione, eseguire il codice HLSL e impostare i punti di interruzione per semplificare la diagnostica del problema.

Per esaminare il vertex shader

  1. Avviare il debug della fase di vertex shader.Nella finestra Fasi pipeline grafica nella fase Vertex shader scegliere il pulsante Avvia debug.

  2. Poiché la fase Assemblaggio input sembra fornire dei buoni dati al vertex shader e la fase Vertex shader sembra non produrre output, si desidera esaminare la struttura di output di vertex shader, output.Passando attraverso il codice HLSL, verrà visualizzata più da vicino la modifica dell'output.

  3. Prima volta che output viene modificato, a cui è scritto il membro worldPos.

    Il valore di "output.worldPos" sembra ragionevole

    Poiché il suo valore sembra essere adeguato, continuare a scorrere il codice fino alla riga successiva che modifica output.

  4. Volta successiva che output viene modificato, il membro a cui è scritto pos.

    Il valore di "output.pos" è stato azzerato

    Questa volta, il valore del membro pos, tutti zero, sembra sospetto.Quindi si desidera Determinare in che modo output.pos ha restituito un valore costituito da tutti zero.

  5. Notare che output.pos accetta il valore di una variabile denominata temp.Nella riga precedente, si vedrà che il valore temp è il risultato di moltiplicazione del valore precedente per una costante denominata projection.Si presume che il valore bene diffidare da temp è il risultato della moltiplicazione.Quando si sofferma il puntatore su projection, notare che il valore è costituito da tutti zeri.

    La matrice di proiezione contiene una trasformazione errata

    In questo scenario, un'analisi rivela che il valore sospetto di temp è provocato molto probabilmente dalla relativa moltiplicazione per projection e poiché projection è una costante destinata a contenere una matrice di proiezione, risulta evidente che non deve contenere zeri.

Dopo aver constatato che la projection della costante HLSL (passata nello shader dall'applicazione) è probabilmente l'origine del problema, il prossimo passo è di individuare la posizione nel codice sorgente dell'applicazione in cui il buffer costante è stato compilato.È possibile utilizzare Stack di chiamate eventi grafici per individuare questa posizione.

Per individuare il punto in cui è impostata la costante nel codice sorgente dell'app

  1. Aprire la finestra Stack di chiamate eventi grafici.Sulla barra degli strumenti Diagnostica grafica scegliere Stack di chiamate eventi grafici.

  2. Spostarsi nello stack di chiamate nel codice sorgente dell'app.Nella finestra Stack di chiamate eventi grafici scegliere la chiamata in primo piano per verificare se il buffer costante viene riempito in tale chiamata.In caso contrario, continuare nello stack di chiamate fino a individuare dove viene riempito.In questo scenario, si scoprirà che il buffer costante viene riempito, utilizzando l'API Direct3D UpdateSubresource, nello stack di chiamate in una funzione denominata MarbleMaze::Rendere che il valore proviene da un oggetto buffer costante denominato m_marbleConstantBufferData:

    Codice che imposta il buffer costanti dell'oggetto

    SuggerimentoSuggerimento

    Se si esegue contemporaneamente il debug dell'applicazione, è possibile impostare un punto di interruzione in tale posizione che verrà raggiunto al momento del rendering del frame successivo.È quindi possibile controllare i membri di m_marbleConstantBufferData per verificare che il valore del membro projection sia impostato su tutti zeri quando il buffer delle costanti è completo.

Dopo avere trovato la posizione in cui viene compilato il buffer costante rilevato che i valori provengono dal m_marbleConstantBufferData variabile, è necessario determinare dove il membro m_marbleConstantBufferData.projection è impostato sugli zeri.È possibile utilizzare Trova tutti i riferimenti per analizzare rapidamente il codice che modifica il valore di m_marbleConstantBufferData.projection.

Per individuare il punto in cui è impostato il membro di proiezione nel codice sorgente dell'app

  1. Trova i riferimenti a m_marbleConstantBufferData.projectionAprire il menu di scelta rapida per la variabile m_marbleConstantBufferData, quindi scegliere Trova tutti i riferimenti.

  2. Per passare alla riga del codice sorgente dell'applicazione in cui il membro projection è stato modificato, selezionare la riga nella finestra Risultati ricerca simbolo.Poiché il primo risultato che modifica il membro di proiezione non può essere la causa del problema, potrebbe essere necessario esaminare diverse aree del codice sorgente dell'applicazione.

Dopo avere trovato la posizione in cui è impostato m_marbleConstantBufferData.projection, è possibile esaminare il codice sorgente esistente per determinare l'origine del valore non corretto.In questo scenario, si individua il valore m_marbleConstantBufferData.projection impostato su una variabile locale denominata projection prima che sia inizializzata con un valore fornito dal codice m_camera->GetProjection(&projection); sulla riga successiva.

Proiezione marmo impostata prima dell'inizializzazione

Per risolvere il problema, spostare la riga di codice che imposta il valore di m_marbleConstantBufferData.projection dopo la riga che inizializza il valore della variabile locale projection.

Codice sorgente C++ corretto

Dopo avere corretto il codice, è possibile ricompilarlo ed eseguire nuovamente l'applicazione per rilevare la risoluzione del problema di rendering:

Oggetto nuovamente visibile.