Condividi tramite


Disegno indiretto

Il disegno indiretto consente di spostare alcuni attraversamento della scena e di spostamento dalla CPU alla GPU, migliorando così le prestazioni. Il buffer dei comandi può essere generato dalla CPU o dalla GPU.

Firme dei comandi

L'oggetto firma del comando (ID3D12CommandSignature) consente alle app di specificare il disegno indiretto, in particolare impostando quanto segue:

All'avvio, un'app crea un piccolo set di firme dei comandi. In fase di esecuzione, l'applicazione riempie un buffer con i comandi (tramite qualsiasi mezzo scelto dallo sviluppatore dell'app). I comandi che contengono facoltativamente lo stato da impostare per le viste del buffer dei vertici, le viste del buffer di indice, le costanti radice e i descrittori radice (SRV/UAV/CBV non elaborati o strutturati). Questi layout di argomenti non sono specifici dell'hardware in modo che le app possano generare direttamente i buffer. La firma del comando eredita lo stato rimanente dall'elenco dei comandi. L'app chiama quindi ExecuteIndirect per indicare alla GPU di interpretare il contenuto del buffer degli argomenti indiretti in base al formato definito da una firma di comando specifica.

Se la firma del comando modifica gli argomenti radice, questo viene archiviato all'interno della firma del comando come subset di una firma radice.

Non viene restituito alcuno stato della firma del comando all'elenco dei comandi al termine dell'esecuzione. Tuttavia, dopo ExecuteIndirect, tutte le associazioni vengono reimpostate su valori noti. In particolare:

  • Se la firma del comando associa un buffer dei vertici a uno slot specifico, dopo la chiamata a ExecuteIndirect , un buffer dei vertici NULL viene associato a tale slot.
  • Se la firma del comando associa un buffer di indice, dopo ExecuteIndirect viene associato un buffer di indice NULL.
  • Se la firma del comando imposta una costante radice, dopo la chiamata a ExecuteIndirect , il valore della costante radice viene impostato su 0.
  • Se la firma del comando imposta una visualizzazione radice (CBV/SRV/UAV), dopo la chiamata a ExecuteIndirect , la visualizzazione radice viene impostata su una visualizzazione NULL.

Come esempio di uso delle firme dei comandi: si supponga che uno sviluppatore di app voglia specificare una costante radice univoca per ogni chiamata di disegno nel buffer degli argomenti indiretti. L'app creerebbe una firma di comando che consente al buffer degli argomenti indiretti di specificare i parametri seguenti per ogni chiamata di disegno:

  • Valore di una costante radice.
  • Argomenti di disegno (conteggio vertici, numero di istanze e così via).

Il buffer degli argomenti indiretti generato dall'applicazione conterrà una matrice di record a dimensione fissa. Ogni struttura corrisponde a una chiamata di disegno. Ogni struttura contiene gli argomenti di disegno e il valore della costante radice. Il numero di chiamate di disegno viene specificato in un buffer visibile dalla GPU separato.

Di seguito è riportato un buffer dei comandi di esempio generato dall'app:

formato del buffer dei comandi

Strutture del buffer degli argomenti indiretti

Le strutture seguenti definiscono la modalità di visualizzazione di argomenti specifici in un buffer di argomenti indiretti. Queste strutture non vengono visualizzate in alcuna API D3D12. Le applicazioni usano queste definizioni durante la scrittura in un buffer di argomenti indiretti (con CPU o GPU):

Creazione della firma del comando

Per creare una firma di comando, usare gli elementi api seguenti:

L'ordinamento degli argomenti all'interno di un buffer di argomenti indiretti viene definito in modo che corrisponda esattamente all'ordine degli argomenti specificati nel parametro pArguments di D3D12_COMMAND_SIGNATURE_DESC. Tutti gli argomenti per una chiamata di disegno (grafica)/dispatch (calcolo) all'interno di un buffer di argomenti indiretti vengono compressi strettamente. Tuttavia, le applicazioni possono specificare uno stride di byte arbitrario tra i comandi draw/dispatch in un buffer di argomenti indiretti.

La firma radice deve essere specificata se e solo se la firma del comando modifica uno degli argomenti radice.

Per la radice SRV/UAV/CBV, le dimensioni specificate dall'applicazione sono in byte. Il livello di debug convaliderà le restrizioni seguenti sull'indirizzo:

  • CBV: l'indirizzo deve essere un multiplo di 256 byte.
  • SRV/UAV non elaborato: l'indirizzo deve essere un multiplo di 4 byte.
  • SRV/UAV strutturato: l'indirizzo deve essere un multiplo dello stride di byte della struttura (dichiarato nello shader).

Una determinata firma di comando è un disegno o una firma del comando di calcolo. Se una firma di comando contiene un'operazione di disegno, si tratta di una firma di comando grafica. In caso contrario, la firma del comando deve contenere un'operazione dispatch ed è una firma del comando di calcolo.

Le sezioni seguenti illustrano alcune firme di comando di esempio.

Nessuna modifica all'argomento

In questo esempio, il buffer degli argomenti indiretti generato dall'applicazione contiene una matrice di strutture a 36 byte. Ogni struttura contiene solo i cinque parametri passati a DrawIndexedInstanced (più riempimento).

Il codice per creare la descrizione della firma del comando è il seguente:

D3D12_INDIRECT_ARGUMENT_DESC Args[1];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 36;
ProgramDesc.NumArgumentDescs = 1;
ProgramDesc.pArguments = Args;

Il layout di una singola struttura all'interno di un buffer di argomenti indiretti è:

Byte Descrizione
0:3 IndexCountPerInstance
4:7 InstanceCount
8:11 StartIndexLocation
12:15 BaseVertexLocation
16:19 StartInstanceLocation
20:35 Padding

 

Costanti radice e buffer dei vertici

In questo esempio, ogni struttura in un buffer di argomenti indiretti modifica due costanti radice, modifica un'associazione di buffer dei vertici ed esegue un'operazione di disegno non indicizzata. Non esiste alcuna spaziatura interna tra le strutture.

Il codice per creare la descrizione della firma del comando è:

D3D12_INDIRECT_ARGUMENT_DESC Args[4];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[0].Constant.RootParameterIndex = 2;
Args[0].Constant.DestOffsetIn32BitValues = 0;
Args[0].Constant.Num32BitValuesToSet = 1;

Args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[1].Constant.RootParameterIndex = 6;
Args[1].Constant.DestOffsetIn32BitValues = 0;
Args[1].Constant.Num32BitValuesToSet = 1;

Args[2].Type = D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW;
Args[2].VertexBuffer.Slot = 3;

Args[3].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 40;
ProgramDesc.NumArgumentDescs = 4;
ProgramDesc.pArguments = Args;

Il layout di una singola struttura all'interno del buffer di argomenti indiretti è il seguente:

Byte Descrizione
0:3 Dati per l'indice dei parametri radice 2
4:7 Dati per l'indice dei parametri radice 6
8:15 Indirizzo virtuale di VB nello slot 3 (64 bit)
16:19 Dimensioni VB
20:23 Sride VB
24:27 VertexCountPerInstance
28:31 InstanceCount
32:35 StartVertexLocation
36:39 StartInstanceLocation

 

Esercitazioni video sull'apprendimento avanzato DirectX: Eseguire il culling di GPU indirette e asincrone

Disegno indiretto e culling GPU: procedura dettagliata del codice

Rendering