Cenni preliminari sugli heap del descrittore

Gli heap del descrittore contengono molti tipi di oggetto che non fanno parte di un oggetto Stato pipeline (PSO), ad esempio viste risorse shader (SRV), viste di accesso non ordinato (UAV), viste buffer costanti (CBV) e campionatori.

Scopo degli heap del descrittore

Lo scopo principale di un heap descrittore consiste nell'includere la maggior parte dell'allocazione di memoria necessaria per archiviare le specifiche del descrittore dei tipi di oggetto a cui fanno riferimento gli shader per il più grande possibile di una finestra di rendering (idealmente un intero frame di rendering o più). Se un'applicazione sta cambiando le trame che la pipeline vede rapidamente dall'API, deve esserci spazio nell'heap del descrittore per definire le tabelle del descrittore in tempo reale per ogni set di stato necessario. L'applicazione può scegliere di riutilizzare le definizioni se le risorse vengono usate di nuovo in un altro oggetto, ad esempio o semplicemente assegnare lo spazio heap in sequenza mentre cambia vari tipi di oggetto.

Gli heap del descrittore consentono anche ai singoli componenti software di gestire l'archiviazione del descrittore separatamente l'uno dall'altro.

Tutti gli heap sono visibili alla CPU. L'applicazione può anche richiedere quali proprietà di accesso alla CPU devono avere un heap descrittore ( se presente): scrittura combinata, writeback e così via. Le app possono creare tutti gli heap descrittori desiderati con le proprietà desiderate. Le app hanno sempre la possibilità di creare heap del descrittore puramente per scopi di gestione temporanea senza vincoli di dimensioni e copia negli heap descrittori usati per il rendering in base alle esigenze.

Esistono alcune restrizioni per ciò che può essere usato nello stesso heap del descrittore. Le voci CBV, UAV e SRV possono trovarsi nello stesso heap del descrittore. Tuttavia, le voci samplers non possono condividere un heap con voci CBV, UAV o SRV. In genere, sono disponibili due set di heap del descrittore, uno per le risorse comuni e il secondo per gli esempi.

L'uso degli heap del descrittore da Direct3D 12 rispecchia ciò che fa la maggior parte dell'hardware GPU, che è quello di richiedere descrittori in tempo reale solo negli heap del descrittore o semplicemente che sono necessari meno bit di indirizzamento se vengono usati questi heap. Direct3D 12 richiede l'uso degli heap del descrittore, non è possibile inserire descrittori in memoria.

Gli heap del descrittore possono essere modificati immediatamente dalla CPU, non è possibile modificare un heap del descrittore dalla GPU.

Sincronizzazione

Il contenuto dell'heap del descrittore può essere modificato prima, durante e dopo la registrazione degli elenchi di comandi che vi fanno riferimento. Tuttavia, i descrittori non possono essere modificati mentre un elenco di comandi inviato per l'esecuzione potrebbe fare riferimento a tale posizione, perché potrebbe richiamare una race condition.

Binding

Al massimo un heap combinato CBV/SRV/UAV e un heap sampler può essere associato in qualsiasi momento. Questi heap vengono condivisi tra le pipeline grafiche e di calcolo (descritte nei relativi PSO).

Cambio di heap

È accettabile per un'applicazione cambiare heap all'interno dello stesso elenco di comandi o in versioni diverse usando le API SetDescriptorHeaps e Reset . In alcuni componenti hardware può trattarsi di un'operazione costosa, che richiede un blocco GPU per scaricare tutto il lavoro che dipende dall'heap descrittore attualmente associato. Di conseguenza, se è necessario modificare gli heap del descrittore, le applicazioni devono provare a farlo quando il carico di lavoro GPU è relativamente leggero, limitando forse le modifiche all'inizio di un elenco di comandi.

Pacchetti

Con i bundle può essere presente una sola chiamata al metodo SetDescriptorHeaps e il descrittore set deve corrispondere esattamente a quelli dell'elenco di comandi che chiama il bundle. Se il bundle non modifica le tabelle del descrittore, non è necessario impostare gli heap del descrittore.

Per un elenco di chiamate API che non possono essere usate con bundle, vedere Creazione e registrazione di elenchi di comandi e bundle.

Gestione

Per eseguire il rendering di tutti gli oggetti in una scena, saranno necessari molti descrittori e sono disponibili alcune strategie di gestione diverse che è possibile seguire.

La strategia più semplice consiste nel compilare una nuova area dell'heap del descrittore con tutti i requisiti per la chiamata di disegno successiva. Quindi, appena prima di eseguire la chiamata di disegno nell'elenco dei comandi, un puntatore alla tabella descrittore verrebbe impostato sull'inizio della tabella appena popolata. Lo svantaggio è che non è necessario registrare dove un descrittore specifico si trova nell'heap.

Lo svantaggio di questa strategia è che potrebbe esserci una grande ripetizione di descrittori nell'heap del descrittore, soprattutto quando viene eseguito il rendering di una scena molto simile e che lo spazio dell'heap del descrittore verrà usato rapidamente. Gli heap del descrittore separati per quelli di cui viene eseguito il rendering nella GPU e per quelli registrati dalla CPU, probabilmente sarebbero necessari per evitare conflitti. In alternativa, è possibile usare un sistema di allocazione secondaria.

Inoltre, il sistema di base potrebbe essere ulteriormente ottimizzato mediante un uso attento di tabelle descrittori sovrapposte da una chiamata di disegno alla successiva, in modo che vengano aggiunti solo i nuovi descrittori necessari.

Una strategia più efficiente rispetto a quella di base consiste nel precompilare gli heap del descrittore con descrittori necessari per gli oggetti (o i materiali) noti come parte della scena. L'idea è che è necessario solo impostare la tabella del descrittore in fase di disegno, perché l'heap del descrittore viene popolato in anticipo.

Una variante della strategia di pre-riempimento consiste nel considerare l'heap del descrittore come una matrice enorme, contenente tutti i descrittori necessari in posizioni note fisse. La chiamata di disegno deve quindi ricevere solo un set di costanti che sono gli indici nella matrice di in cui devono essere usati i descrittori.

Un'ulteriore ottimizzazione consiste nel garantire che le costanti radice e i descrittori radice contengano quelle che cambiano più di frequente, anziché inserire costanti nell'heap del descrittore. Per la maggior parte dell'hardware, questo è un modo efficiente di gestire le costanti.

In pratica, un motore grafico potrebbe usare una strategia diversa in situazioni diverse e combinare elementi di ogni strategia in base ai requisiti di disegno specifici.

Heap descrittore