Share via


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 di quanto mai prima. Essendo più vicino all'hardware, Direct3D 12 è più veloce e più efficiente. Tuttavia, il compromesso dell'app ha aumentato la velocità e l'efficienza con Direct3D 12 è che sei responsabile di più attività rispetto a Direct3D 11.

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

L'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, la sincronizzazione CPU-GPU è ora la responsabilità esplicita dell'app e non viene più eseguita in modo implicito dal runtime, perché è in Direct3D 11. Questo fatto significa anche che non viene eseguita alcuna verifica automatica dei rischi della pipeline da Direct3D 12, quindi anche questa è la responsabilità delle app.
  • In Direct3D 12 le app sono responsabili degli aggiornamenti dei dati di pipelining. Vale a dire, 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 precedente. Ciò consente alla GPU di continuare a usare i dati precedenti mentre l'app inserisce i dati nel nuovo buffer. Non è necessaria alcuna gestione di memoria aggiuntiva 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 di vertice dinamici, trame dinamiche e così via) vengono controllati in modo esplicito dall'app. Questi aggiornamenti dinamici includono qualsiasi recinzione o buffering GPU richiesto. L'app è responsabile della conservazione della memoria disponibile fino a quando non è più necessaria.
  • Direct3D 12 usa il conteggio dei riferimenti in stile COM solo per la durata delle interfacce (usando il modello di riferimento debole di Direct3D associato alla durata del dispositivo). Tutte le risorse e la durata della memoria della descrizione sono l'unica responsabile dell'app da mantenere per la durata corretta e non sono conteggiate. Direct3D 11 usa anche il conteggio dei riferimenti per gestire la durata delle dipendenze dell'interfaccia.

Gestione della residenza della memoria fisica

Un'applicazione Direct3D 12 deve impedire le condizioni di gara tra più code, più schede e i thread della CPU. D3D12 non sincronizza più la CPU e la GPU, né supporta meccanismi pratici per la ridenominazione o il multi-buffering delle risorse. Le recinzioni devono essere usate per evitare più unità di elaborazione dalla memoria sovrascriva prima che un'altra unità di elaborazione venga terminata usandola.

L'applicazione Direct3D 12 deve assicurarsi che i dati si trovano in memoria mentre la GPU lo legge. La memoria usata da ogni oggetto viene resa residente durante la creazione dell'oggetto. Le applicazioni che chiamano questi metodi devono usare recinzioni per garantire che la GPU non accede agli oggetti che sono stati rimossi.

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

Fare riferimento a Gestione della memoria in Direct3D 12.

Oggetti dello stato della pipeline

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

Direct3D 12 risolve questo schema unificando gran parte dello stato della pipeline in oggetti stato della pipeline non modificabili (PSO), che vengono finalizzati alla creazione. I driver e l'hardware possono quindi convertire immediatamente l'oggetto PSO in qualsiasi istruzione nativa dell'hardware e lo stato necessari per eseguire il lavoro della GPU. È comunque possibile modificare dinamicamente quale PSO è in uso, ma a tale scopo, l'hardware deve copiare solo la quantità minima di stato pre-calcolata direttamente nei registri hardware, anziché calcolare lo stato hardware al volo. Usando gli oggetti PSO, il sovraccarico delle chiamate di disegno è ridotto in modo significativo e molte più chiamate di disegno possono verificarsi per ogni frame. Per altre informazioni sugli oggetti PSO, vedere Gestione dello stato della pipeline grafica in Direct3D 12.

Elenchi di comandi e bundle

In Direct3D 11, tutti gli invii di lavoro vengono eseguiti 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 per loro. I contesti posticipati in Direct3D 11 non mappano perfettamente all'hardware, quindi un lavoro relativamente piccolo può essere eseguito in essi.

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 di trama e buffer sono necessarie e gli argomenti per tutte le chiamate di disegno. Poiché ogni elenco di comandi è autonomo e non eredita alcun stato, il driver può pre-calcolare tutti i comandi GPU necessari in anticipo e in modo thread libero. L'unico processo seriale necessario è l'invio finale degli elenchi di comandi alla GPU tramite la coda di comandi.

Oltre agli elenchi di comandi, Direct3D 12 introduce anche un secondo livello di pre-calcolo del lavoro: bundle. A differenza degli elenchi di comandi, che sono completamente autonomi e vengono in genere costruiti, inviati una volta e eliminati, 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 dei comandi usando risorse diverse. In quest'ultimo caso, il driver di visualizzazione deve 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.

Descrittore heaps e tabelle

L'associazione di risorse in Direct3D 11 è estremamente astratta e conveniente, ma lascia molte funzionalità hardware moderne sottoutilizzate. In Direct3D 11, i giochi creano oggetti di visualizzazione delle risorse, quindi associano tali visualizzazioni a diversi slot in varie fasi shader nella pipeline. Shader, a sua volta, legge i dati da tali slot di associazione espliciti, fissi al momento del disegno. Questo modello significa che ogni volta che un gioco disegna usando risorse diverse, deve riassegnare visualizzazioni diverse a slot diversi e chiamare di nuovo il disegno. Questo caso rappresenta anche il sovraccarico che può essere eliminato usando completamente le funzionalità hardware moderne.

Direct3D 12 modifica il modello di associazione in modo da corrispondere all'hardware moderno e migliora notevolmente le prestazioni. Anziché richiedere visualizzazioni di risorse autonome e mapping esplicito agli slot, Direct3D 12 fornisce un heap 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 hardware (descrittore) in memoria. 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 descrittore è già stato popolato con i dati di descrittore specifici dell'hardware appropriati, la modifica delle tabelle del descrittore è un'operazione estremamente a basso costo.

Oltre alle prestazioni migliorate offerte dal descrittore heaps e dalle tabelle, Direct3D 12 consente anche alle risorse di essere indicizzate dinamicamente negli shader, che offre flessibilità senza precedenti e sblocca nuove tecniche di rendering. Ad esempio, i motori di rendering posticipati moderni codificano in genere un identificatore di materiale o oggetto di un tipo al buffer g intermedio. In Direct3D 11, questi motori devono prestare attenzione a evitare l'uso di troppi materiali, come anche troppi in un buffer g possono rallentare significativamente il passaggio di rendering finale. Con risorse indicizzate in modo dinamico, una scena con migliaia di materiali può essere finalizzata appena una con solo dieci.

Per altre informazioni sugli heaps e sulle tabelle del descrittore, vedere Associazione di risorse e differenze nel modello di associazione da Direct3D 11.

Conversione da Direct3D 11

La conversione da Direct3D 11 è un processo coinvolto, descritto nella conversione da Direct3D 11 a Direct3D 12. Fare riferimento anche all'intervallo di opzioni in Uso con Direct3D 11, Direct3D 10 e Direct2D.

Informazioni su Direct3D 12