Share via


Conversione da Direct3D 11 a Direct3D 12

Questa sezione fornisce alcune indicazioni sulla conversione da un motore grafico Direct3D 11 personalizzato a Direct3D 12.

Creazione del dispositivo

Sia Direct3D 11 che Direct3D 12 condividono un modello di creazione di dispositivi simile. I driver Direct3D 12 esistenti sono tutti D3D_FEATURE_LEVEL_11_0 o meglio, quindi è possibile ignorare i livelli di funzionalità precedenti e le limitazioni associate.

Tenere presente anche che con Direct3D 12 è necessario enumerare in modo esplicito le informazioni sul dispositivo usando interfacce DXGI. In Direct3D 11 è possibile concatenare il dispositivo DXGI dal dispositivo Direct3D e questo non è supportato per Direct3D 12.

La creazione di un dispositivo software WARP in Direct3D 12 viene eseguita fornendo una scheda esplicita ottenuta da IDXGIFactory4::EnumWarpAdapter. Il dispositivo WARP per Direct3D 12 è disponibile solo nei sistemi con la funzionalità facoltativa strumenti di grafica abilitata.

Nota

Non esiste alcun equivalente a D3D11CreateDeviceAndSwapChain. Anche con Direct3D 11, sconsigliamo l'uso di questa funzione perché spesso è meglio creare il dispositivo e lo scambio in passaggi distinti.

Risorse di commit

Gli oggetti creati con le interfacce seguenti in Direct3D 11 si traducono in quello che viene denominato "risorse commit" in Direct3D 12. Una risorsa di cui è stato eseguito il commit è una risorsa con spazio indirizzi virtuale e pagine fisiche associate. Si tratta di un concetto del modello di memoria wdD2 (WdD2) di Microsoft Windows Device Driver, basato su Direct3D 12.

Risorse Direct3D 11:

In Direct3D 12 sono tutti rappresentati da ID3D12Resource e ID3D12Device::CreateCommittedResource.

Risorse riservate

Le risorse riservate sono risorse in cui è stato allocato solo lo spazio degli indirizzi virtuali, la memoria fisica non viene allocata finché non viene assegnata una chiamata a ID3D12Device::CreateHeap. Si tratta essenzialmente dello stesso concetto delle risorse riquadri in Direct3D 11.

I flag (D3D11_RESOURCE_MISC_FLAG) usati in Direct3D 11 per configurare le risorse riquadri, quindi eseguirne il mapping alla memoria fisica.

  • D3D11_RESOURCE_MISC_TILED
  • D3D11_RESOURCE_MISC_TILE_POOL

Caricamento dei dati

In Direct3D 11 è presente l'aspetto di una singola sequenza temporale (chiamate che seguono una sequenza, ad esempio i dati inizializzati con D3D11_SUBRESOURCE_DATA, viene eseguita una chiamata a ID3D11DeviceContext::UpdateSubresource e quindi una chiamata a ID3D11DeviceContext::Map). Il numero di copie create dei dati non è ovvio per uno sviluppatore Direct3D 11.

In Direct3D 12 sono presenti due sequenze temporali, la sequenza temporale della GPU (configurata dalle chiamate a CopyTextureRegion e CopyBufferRegion dalla memoria mappabile) e la sequenza temporale della CPU (determinata dalle chiamate a Map). Le funzioni helper vengono fornite (nel file d3dx12.h) denominate Updatesubresources che usano una sequenza temporale condivisa. Esistono diverse varianti di questa funzione helper, una che usa ID3D12Device::GetCopyableFootprints, un'altra che usa un meccanismo di allocazione heap e un'altra che usa un meccanismo di allocazione dello stack. Queste funzioni helper copiano le risorse nella GPU e nella CPU, tramite un'area di gestione temporanea intermedia della memoria.

In genere la GPU e la CPU hanno una propria copia di una risorsa associata alla propria sequenza temporale. L'approccio della sequenza temporale condivisa gestisce in modo analogo due copie.

Oggetti shader e shader

In Direct3D 11 è disponibile un sacco di creazione di oggetti shader e state e l'impostazione dello stato di tali oggetti usando i metodi di creazione ID3D11Device e i metodi di set ID3D11DeviceContext. In genere viene effettuato un numero elevato di chiamate a questi metodi, che vengono quindi combinati in fase di disegno dal driver per impostare lo stato della pipeline corretto.

In Direct3D 12 questa impostazione dello stato della pipeline è stata combinata in un singolo oggetto (CreateComputePipelineState per un motore di calcolo e CreateGraphicsPipelineState per un motore grafico), che viene quindi collegato a un elenco di comandi prima della chiamata di disegno con una chiamata a SetPipelineState.

Queste chiamate sostituiscono tutte le singole chiamate per impostare shader, layout di input, stato di blend, stato rasterizer, stato stencil di profondità e così via, in Direct3D 11

  • Metodi del dispositivo 11: CreateInputLayout, CreateXShader, CreateDepthStencilStatee CreateRasterizerState.
  • Metodi Contesto dispositivo 11: IASetInputLayout, xxSetShaderOMSetBlendState, , OMSetDepthStencilStatee RSSetState.

Anche se Direct3D 12 può supportare BLOB shader compilati meno recenti, gli shader devono essere compilati usando shader Model 5.1 con le API FXC/D3DCompile o usando il compilatore DXIL DXC 6. È necessario convalidare il supporto di Shader Model 6 con CheckFeatureSupport e D3D12_FEATURE_SHADER_MODEL.

Invio del lavoro alla GPU

in Direct3D 11 c'è poco controllo sul funzionamento dell'invio, viene in gran parte gestito dal driver, anche se alcuni controlli sono abilitati tramite l'ID3D11DeviceContext::Flush e IDXGISwapChain1::P resent1 chiamate.

In Direct3D 12 l'invio di lavoro è molto esplicito e controllato dall'app. Il costrutto primario per l'invio del lavoro è l'ID3D12GraphicsCommandList, usato per registrare tutti i comandi delle app (ed è abbastanza simile nel concetto al contesto posticipato ID3D11). L'archivio di backup per un elenco di comandi viene fornito dal driver ID3D12CommandAllocator, che consente all'app di gestire l'utilizzo della memoria dell'elenco di comandi esponendo effettivamente la memoria che il driver Direct3D 12 userà per archiviare l'elenco dei comandi.

Infine l'ID3D12CommandQueue è una coda first-in first-out, che archivia l'ordine corretto degli elenchi di comandi per l'invio alla GPU. Solo quando un elenco di comandi ha completato l'esecuzione nella GPU, l'elenco di comandi successivo dalla coda verrà inviato dal driver.

In Direct3D 11 non esiste alcun concetto esplicito di una coda di comandi. Nella configurazione comune per Direct3D 12, l'elenco di comandi attualmente aperto D3D12_COMMAND_LIST_TYPE_DIRECT per il frame corrente può essere considerato analogo al contesto immediato Direct3D 11. In questo modo vengono fornite molte delle stesse funzioni.

D3D11DeviceContext ID3D12GraphicsCommand List
ClearDepthStencilView ClearDepthStencilView
ClearRenderTargetView ClearRenderTargetView
ClearUnorderedAccess* ClearUnorderedAccess*
Draw, DrawInstanced DrawInstanced
DrawIndexed, DrawIndexedInstanced DrawIndexedInstanced
Dispatch Dispatch
IASetInputLayout, xxSetShader e così via. SetPipelineState
OMSetBlendState OMSetBlendFactor
OMSetDepthStencilState OMSetStencilRef
OMSetRenderTargets OMSetRenderTargets
RSSetViewports RSSetViewports
RSSetScissorRects RSSetScissorRects
Topologia IASetPrimitiveTopology Topologia IASetPrimitiveTopology
IASetVertexBuffers IASetVertexBuffers
IASetIndexBuffer IASetIndexBuffer
ResolveSubresource ResolveSubresource
CopySubresourceRegion CopyBufferRegion
UpdateSubresource CopyTextureRegion
CopyResource CopyResource

Nota

Un elenco di comandi creato con D3D12_COMMAND_LIST_TYPE_BUNDLE è simliar in un contesto posticipato. Direct3D 12 supporta anche l'abiilty per accedere ad alcune funzionalità di un contesto immediato per eseguire il rendering tramite D3D12_COMMAND_LIST_TYPE_COPY e D3D12_COMMAND_LIST_TYPE_COMPUTE tipi di elenco comandi.

Sincronizzazione CPU/GPU

In Direct3D 11 la sincronizzazione CPU/GPU è stata in gran parte automatica e non è stato necessario che l'app mantenga lo stato della memoria fisica.

in Direct3D 12 l'app deve gestire in modo esplicito le due sequenze temporali (CPU e GPU). Ciò richiede che le informazioni siano mantenute, dall'app, sulle risorse necessarie dalla GPU e per quanto tempo. Ciò significa anche che l'app è responsabile della garanzia del contenuto delle risorse (risorse di commit, heaps, allocatori di comando, ad esempio) non cambiano fino al termine dell'uso della GPU.

L'oggetto principale per la sincronizzazione delle sequenze temporali è l'oggetto ID3D12Fence . L'operazione di recinzioni è abbastanza semplice, consentono alla GPU di segnalare quando è stata completata un'attività. La GPU e la CPU possono entrambi segnalare e possono attendere entrambe le recinzioni.

In genere l'approccio è che quando si invia un elenco di comandi per l'esecuzione, un segnale di recinzione viene trasmesso dalla GPU al completamento (al termine della lettura dei dati), consentendo alla CPU di riutilizzare o eliminare le risorse.

In Direct3D 11 il flag ID3D11DeviceContext::Map D3D11_MAP_WRITE_DISCARD essenzialmente considerato ogni risorsa come un'offerta infinita di memoria che l'app potrebbe scrivere in (un processo noto come "ridenominazione"). In Direct3D 12 il processo è esplicito: è necessario allocare memoria aggiuntiva e le barriere devono essere usate per sincronizzare le operazioni. I buffer anello (costituiti da buffer di grandi dimensioni) potrebbero essere una buona tecnica per questo, fare riferimento allo scenario del buffer anello in Gestione risorse basate su recinti.

uso di un buffer anello

Associazione di risorse

Le visualizzazioni in Direct3D 11 (viste delle risorse shader, viste di destinazione di rendering e così via), sono state sostituite in gran parte in Direct3D 12 con il concetto di descrittore. I metodi di creazione esistono ancora in Direct3D 12 (ad esempio CreateShaderResourceView e CreateRenderTargetView), chiamati dopo la creazione dell'heap descrittore, per scrivere i dati nell'heap. L'associazione in Direct3D 12 è ora gestita da handle del descrittore descritti in una firma radice e inviati usando i metodi SetGraphicsRootDescriptorTable o SetComputeRootDescriptorTable .

Mapping dei dettagli delle firme radice tra il numero di slot della firma radice e le tabelle descrittori, in cui la tabella descrittore può contenere riferimenti alle risorse disponibili per vertex shader, pixel shader e gli altri shader, ad esempio buffer costanti, viste delle risorse shader e esempi. Questa flessibilità disconnette lo spazio di registrazione HLSL dallo spazio di associazione API in Direct3D 12, a differenza di Direct3D 11 in cui è presente un mapping tra questi.

Una delle implicazioni di questo sistema è che l'app è responsabile della ridenominazione delle tabelle descrittori, che consente agli sviluppatori di comprendere il costo delle prestazioni della modifica anche di un singolo descrittore per chiamata di disegno.

Una nuova funzionalità di Direct3D 12 è che un'app può controllare quali descrittori sono condivisi tra le fasi dello shader. Nelle risorse Direct3D 11, ad esempio le UAV, vengono condivise tra tutte le fasi dello shader. Abilitando i descrittori per essere disabilitati per determinate fasi shader, i registri usati dai descrittori disabilitati sono disponibili per essere usati dai descrittori abilitati per una fase particolare dello shader.

La tabella seguente mostra una firma radice di esempio.

Slot del parametro radice Voce tabella descrittore
0 Intervallo di descrittori VS b0-b13
1 Intervallo di descrittori VS t0-t127
2 Intervallo di descrittori VS s0-s16
3 Intervallo di descrittori PS b0-b13
...
14 Intervallo descrittore DS s0-16
15 Intervallo di descrittori condivisi u0-u63

 

Stato della risorsa

Nello stato della risorsa Direct3D 11 non viene gestito dall'app, ma dal driver.

In Direct3D 12 mantenere lo stato della risorsa diventa la responsabilità dell'app, per abilitare il parallelismo completo nella registrazione degli elenchi di comandi: l'app deve gestire le sequenze temporali di registrazione per gli elenchi di comandi (che possono essere eseguite in parallelo) e le sequenze temporali di esecuzione che devono essere sequenziali.

Una transizione dello stato della risorsa viene gestita dal metodo ResourceBarrier . Principalmente l'app deve informare il driver quando l'utilizzo delle risorse cambia. Ad esempio, se una risorsa viene usata come destinazione di rendering e quindi deve essere usata come input per un vertex shader nella chiamata di disegno successiva, questo potrebbe richiedere un breve stallo nell'operazione GPU per completare l'operazione di destinazione del rendering prima di gestire il vertex shader.

Questo sistema consente la sincronizzazione di granularità fine (stalli GPU) della pipeline grafica, nonché gli scaricamenti della cache e, eventualmente, alcune modifiche al layout di memoria(ad esempio la visualizzazione di destinazione di rendering alla decompressione della visualizzazione stencil di profondità).

Questo è noto come barriera di transizione. Esistono altri tipi di barriere, in Direct3D 11 l'ID3D11DeviceContext2::TiledResourceBarrier ha abilitato la stessa memoria fisica da usare da due risorse riquadri diverse. In Direct3D 12 viene definito "barriera di aliasing". Le barriere di aliasing possono essere usate sia per le risorse riquadri che per le risorse posizionate in Direct3D 12. Inoltre c'è la barriera UAV. In Direct3D 11 tutte le operazioni di invio e disegno UAV devono essere serializzate, anche se queste operazioni possono essere pipelinete o funzionanti in parallelo. Per Direct3D 12 questa restrizione viene rimossa dall'aggiunta di una barriera UAV. Una barriera UAV garantisce che le operazioni UAV siano sequenziali, quindi se una seconda operazione richiede che il primo completamento, il secondo sarà costretto ad attendere l'aggiunta della barriera. L'operazione predefinita per le UAV è semplicemente che le operazioni procederanno il più rapidamente possibile.

Chiaramente ci sono miglioramenti delle prestazioni se un carico di lavoro può essere parallelizzato.

Swapchains

La catena di scambio DXGI è la base per le catene di scambio in Direct3D 11 e 12. Esistono alcune differenze minori, in Direct3D 11 i tre tipi di catena di scambio sono SEQUENZIALI, DISCARD e FLIP_SEQUENTIAL. Per Direct3D 12 sono disponibili solo due tipi: FLIP_SEQUENTIAL e FLIP_DISCARD. Come indicato in precedenza, è necessario creare in modo esplicito la swapchain tramite IDXGIFactory4 o versioni successive e usare la stessa interfaccia per qualsiasi enumerazione adapter.

In Direct3D 11 è disponibile la rotazione automatica del backbuffer: è necessaria una sola visualizzazione di destinazione di rendering per il buffer indietro 0. Nella rotazione del buffer Direct3D 12 è esplicito, è necessario avere una visualizzazione di destinazione di rendering per ogni buffer back. Usare il metodo IDXGISwapChain3::GetCurrentBackBufferIndex per selezionarne uno da eseguire. Anche in questo caso, questa flessibilità aggiuntiva consente una maggiore parallelizzazione.

Nota

Anche se esistono numerosi modi per configurare l'applicazione, in genere le applicazioni hanno un ID3D12CommandAllocator per buffer della catena di scambio. Ciò consente all'applicazione di procedere alla compilazione di un set di comandi per il frame successivo mentre la GPU esegue il rendering della GPU precedente.

Rendering di funzioni fisse

In Direct3D 11 sono stati creati alcuni metodi che semplificavano varie operazioni di livello superiore, ad esempio GenerateMips (creazione di catene mip complete) e DrawAuto (usando l'output di flusso come input shader senza ulteriore input dall'app). Questi metodi non sono disponibili in Direct3D 12, l'app deve gestire queste operazioni creando shader per eseguirle.

Quote e fine

La tabella seguente mostra una serie di funzionalità simili tra Direct3D 11 e 12, ma non sono identiche.

Direct3D 11 Direct3D 12
ID3D11Query ID3D12QueryHeap consente di raggruppare le query, riducendo il costo.
ID3D11Predicate La predicazione è ora abilitata con dati in un buffer completamente trasparente. L'oggetto Direct3D 11 ID3D11Predicate viene sostituito da ID3D12Resource::Map, che deve seguire una chiamata a ResolveQueryData e un'operazione di sincronizzazione GPU usando un recinto per attendere che i dati siano pronti. Fare riferimento a Predicazione.
Contatore nascosto UAV/SO L'app è responsabile dell'allocazione e della gestione dei contatori SO/UAV. Fare riferimento ai contatori di output di flusso e ai contatori UAV.
MinLOD dinamico della risorsa (livello minium di dettaglio) Questa operazione è stata spostata nel descrittore SRV statico MinLOD.
Draw*Indirect/DispatchIndirect I metodi indiretti di disegno vengono tutti uniti nel metodo ExecuteIndirect .
I formati DepthStencil sono interleaved I formati DepthStencil sono planari. Ad esempio, un formato di 24 bit di profondità, 8 bit di stencil verrebbero archiviati nel formato 24/8/24/8... etc in Direct3D 11, ma come 24/24/24... seguito da 8/8/8... in Direct3D 12. Si noti che ogni piano è la propria sottorisorsa in D3D12 (fare riferimento a Sottorisorse).
ResizeTilePool Le risorse riservate possono essere mappate a più heap. Quando un pool di riquadri sarebbe stato ampliato in D3D11, è possibile allocare invece un heap aggiuntivo in D3D12.

 

Esercitazioni video di apprendimento avanzato DirectX: Guida alla conversione da DirectX 11 a DirectX 12

Informazioni su Direct3D 12

Uso di Direct3D 11, Direct3D 10 e Direct2D