Condividi tramite


Modifiche importanti da Direct3D 11 a Direct3D 12

Direct3D 12 rappresenta una significativa partenza dal modello di programmazione Direct3D 11. Direct3D 12 consente alle app di avvicinarsi all'hardware che mai prima. Essendo più vicino all'hardware, Direct3D 12 è più veloce ed efficiente. Tuttavia, il compromesso della tua app ha aumentato la velocità e l'efficienza con Direct3D 12 è che sei responsabile di più attività di quelle con Direct3D 11.

Direct3D 12 è un ritorno alla programmazione di basso livello; offre maggiore controllo sugli elementi grafici dei giochi e delle app introducendo queste nuove funzionalità: gli oggetti per rappresentare lo stato complessivo della pipeline, gli elenchi di comandi e i bundle per l'invio di lavoro e gli heap del descrittore e le tabelle per l'accesso alle risorse.

La tua app ha aumentato la velocità e l'efficienza con Direct3D 12, ma sei responsabile di più attività rispetto a Direct3D 11.

Sincronizzazione esplicita

  • In Direct3D 12, CPU-GPU sincronizzazione è ora la responsabilità esplicita dell'app e non viene più eseguita in modo implicito dal runtime, come avviene in Direct3D 11. Questo significa anche che non viene eseguito alcun controllo automatico dei pericoli delle pipeline da Direct3D 12, quindi anche questo è responsabilità delle app.
  • In Direct3D 12 le app sono responsabili della pipelining degli aggiornamenti dei dati. Ovvero, il modello "Map/Lock-DISCARD" in Direct3D 11 deve essere eseguito manualmente in Direct3D 12. In Direct3D 11, se la GPU usa ancora il buffer quando si chiama ID3D11DeviceContext::Map con D3D11_MAP_WRITE_DISCARD, il runtime restituisce un puntatore a una nuova area di memoria anziché i dati del buffer precedenti. Ciò consente alla GPU di continuare a usare i dati precedenti mentre l'app inserisce i dati nel nuovo buffer. Non è necessaria alcuna gestione aggiuntiva della memoria nell'app; il buffer precedente viene riutilizzato o eliminato automaticamente al termine della GPU.
  • In Direct3D 12, tutti gli aggiornamenti dinamici (inclusi buffer costanti, buffer dei vertici dinamici, trame dinamiche e così via) vengono controllati in modo esplicito dall'app. Questi aggiornamenti dinamici includono eventuali recinzioni GPU o buffering necessari. L'app è responsabile della disponibilità della memoria fino a quando non è più necessaria.
  • Direct3D 12 usa il conteggio dei riferimenti in stile COM solo per le durate delle interfacce (usando il modello di riferimento debole di Direct3D associato alla durata del dispositivo). Tutte le durate di memoria della risorsa e della descrizione sono l'unica responsabile dell'app da mantenere per la durata corretta e non vengono conteggiate. Direct3D 11 usa il conteggio dei riferimenti per gestire anche la durata delle dipendenze dell'interfaccia.

Gestione della residenza della memoria fisica

Un'applicazione Direct3D 12 deve impedire race condition tra più code, più schede e thread CPU. D3D12 non sincronizza più la CPU e la GPU, né supporta meccanismi pratici per la ridenominazione delle risorse o il multi-buffering. I recinti devono essere usati per evitare che più unità di elaborazione sovrascrivano la memoria prima che un'altra unità di elaborazione finisca di usarla.

L'applicazione Direct3D 12 deve garantire che i dati si trovano in memoria mentre la GPU le legge. La memoria utilizzata da ogni oggetto viene resa residente durante la creazione dell'oggetto. Le applicazioni che chiamano questi metodi devono usare recinto per garantire che la GPU non accefra gli oggetti che sono stati rimossi.

Le barriere delle risorse sono un altro tipo di sincronizzazione necessaria, usate per sincronizzare le transizioni di risorse e sottorisorse a un livello molto granulare.

Fare riferimento a gestione della memoria in Direct3D 12.

Oggetti di stato della pipeline

Direct3D 11 consente la manipolazione dello stato della pipeline tramite un ampio set di oggetti indipendenti. Ad esempio, lo stato dell'assembler di input, lo stato del pixel shader, lo stato del rasterizzatore e lo stato di unione dell'output possono essere tutti modificati in modo indipendente. Questa progettazione offre una rappresentazione pratica e relativamente generale della pipeline grafica, ma non usa le funzionalità dell'hardware moderno, principalmente perché i vari stati sono spesso interdipendenti. Ad esempio, molte GPU combinano pixel shader e lo stato di unione dell'output in una singola rappresentazione hardware. Tuttavia, poiché l'API Direct3D 11 consente di impostare separatamente queste fasi della pipeline, il driver di visualizzazione non può risolvere i problemi dello stato della pipeline fino a quando non viene finalizzato lo stato, che non è fino al momento del disegno. Questo schema ritarda la configurazione dello stato hardware, il che significa sovraccarico aggiuntivo e meno chiamate di disegno massime per fotogramma.

Direct3D 12 risolve questo schema unificando gran parte dello stato della pipeline in oggetti dello stato della pipeline non modificabili (PSO), che vengono finalizzati al momento della creazione. I driver e l'hardware possono quindi convertire immediatamente il pso in qualsiasi istruzione e stato nativo dell'hardware per eseguire il lavoro della GPU. È comunque possibile modificare dinamicamente quale PSO è in uso, ma a tale scopo, l'hardware deve solo copiare la quantità minima di stato pre-calcolato direttamente nei registri hardware, invece di calcolare lo stato hardware in tempo reale. L'uso di PSO riduce significativamente il sovraccarico delle chiamate di disegno e molte più chiamate di disegno possono verificarsi per fotogramma. Per altre informazioni sugli oggetti PSO, vedere Gestione dello stato della pipeline grafica in Direct3D 12.

Elenchi di comandi e bundle

In Direct3D 11, tutto l'invio di lavoro viene eseguito tramite il contesto immediato , che rappresenta un singolo flusso di comandi che passano alla GPU. Per ottenere il ridimensionamento multithreading, i giochi hanno anche contesti posticipati disponibili. I contesti posticipati in Direct3D 11 non eseguono il mapping perfettamente all'hardware, quindi è possibile eseguire un lavoro relativamente poco.

Direct3D 12 introduce un nuovo modello per l'invio di lavoro in base agli elenchi di comandi che contengono l'intera quantità di informazioni necessarie per eseguire un determinato carico di lavoro nella GPU. Ogni nuovo elenco di comandi contiene informazioni quali PSO da usare, quali risorse trama e buffer sono necessarie e gli argomenti per tutte le chiamate di disegno. Poiché ogni elenco di comandi è indipendente e non eredita alcuno stato, il driver può pre-calcolare tutti i comandi GPU necessari in anticipo e in modo senza thread. L'unico processo seriale necessario è l'invio finale degli elenchi di comandi alla GPU tramite la coda dei comandi.

Oltre agli elenchi di comandi, Direct3D 12 introduce anche un secondo livello di pre-calcolo di lavoro: bundle. A differenza degli elenchi di comandi, che sono completamente indipendenti e vengono in genere costruiti, inviati una volta e rimossi, i bundle forniscono una forma di ereditarietà dello stato che consente il riutilizzo. Ad esempio, se un gioco vuole disegnare due modelli di caratteri con trame diverse, un approccio consiste nel registrare un elenco di comandi con due set di chiamate di disegno identiche. Ma un altro approccio consiste nel "registrare" un bundle che disegna un singolo modello di caratteri, quindi "riprodurre" il bundle due volte nell'elenco di comandi usando risorse diverse. In quest'ultimo caso, il driver di visualizzazione deve solo calcolare le istruzioni appropriate una sola volta e la creazione dell'elenco di comandi equivale essenzialmente a due chiamate di funzione a basso costo.

Per altre informazioni sugli elenchi di comandi e sui bundle, vedere Invio di lavoro in Direct3D 12.

Heap e tabelle del descrittore

L'associazione di risorse in Direct3D 11 è estremamente astratta e conveniente, ma lascia molte funzionalità hardware moderne sottoutilizzate. In Direct3D 11 i giochi creano visualizzazione oggetti delle risorse, quindi associano tali visualizzazioni a diversi slot in varie fasi dello shader nella pipeline. Gli shader, a loro volta, leggono i dati da tali slot di associazione espliciti, che vengono fissi in fase di disegno. Questo modello significa che ogni volta che un gioco disegnare utilizzando risorse diverse, deve ricollegare visualizzazioni diverse a slot diversi e chiamare di nuovo disegno. Questo caso rappresenta anche un sovraccarico che può essere eliminato utilizzando completamente le funzionalità hardware moderne.

Direct3D 12 modifica il modello di associazione in modo che corrisponda all'hardware moderno e migliori significativamente le prestazioni. Invece di richiedere visualizzazioni di risorse autonome e mapping esplicito agli slot, Direct3D 12 fornisce un heap del descrittore in cui i giochi creano le diverse visualizzazioni delle risorse. Questo schema fornisce un meccanismo per la GPU per scrivere direttamente la descrizione della risorsa nativa dell'hardware (descrittore) nella memoria iniziale. Per dichiarare quali risorse devono essere usate dalla pipeline per una determinata chiamata di disegno, i giochi specificano una o più tabelle descrittori che rappresentano intervalli secondari dell'heap del descrittore completo. Poiché l'heap del descrittore è già stato popolato con i dati del descrittore specifici dell'hardware appropriati, la modifica delle tabelle del descrittore è un'operazione estremamente a basso costo.

Oltre alle prestazioni migliorate offerte dagli heap e dalle tabelle del descrittore, Direct3D 12 consente anche di indicizzare dinamicamente le risorse negli shader, che offre flessibilità senza precedenti e sblocca nuove tecniche di rendering. Ad esempio, i moderni motori di rendering posticipati codificano in genere un identificatore di materiale o oggetto di qualche tipo nel buffer g intermedio. In Direct3D 11, questi motori devono prestare attenzione per evitare l'uso di troppi materiali, perché anche troppi in un buffer g possono rallentare significativamente il passaggio di rendering finale. Con risorse indicizzate dinamicamente, una scena con migliaia di materiali può essere finalizzata altrettanto rapidamente con una sola decina.

Per altre informazioni sugli heap e sulle tabelle del descrittore, vedere resource bindinge differenze nel modello di associazione da Direct3D 11.

Conversione da Direct3D 11

La conversione da Direct3D 11 è un processo coinvolto, descritto in Conversione da Direct3D 11 a Direct3D 12. Vedere anche l'intervallo di opzioni in Uso di Direct3D 11, Direct3D 10 e Direct2D.

Understanding Direct3D 12