C'è molto lavoro necessario sulla CPU per impostare un frame per la GPU e una buona parte di quel lavoro è all'interno del driver grafico. Prima di DX12 / Vulkan, il lavoro del driver grafico era essenzialmente costretto a essere sottoposto a thread singolo dal design dell'API.
La speranza è che DX12 / Vulkan risolvano tale restrizione, consentendo di eseguire il lavoro del driver in parallelo su più thread della CPU all'interno di un frame. Ciò consentirà un uso più efficiente delle CPU multicore, consentendo ai motori di gioco di spingere scene più complesse senza essere vincolati alla CPU. Questa è la speranza: se sarà realizzato nella pratica è qualcosa che dovremo aspettare per vedere nei prossimi anni.
Per elaborare un po ': l'output di un renderer del motore di gioco è un flusso di chiamate API DX / GL che descrivono la sequenza di operazioni per il rendering di un frame. Tuttavia, esiste una grande distanza tra il flusso di chiamate API e gli effettivi buffer dei comandi binari consumati dall'hardware della GPU. Il driver deve "compilare" le chiamate API nel linguaggio macchina della GPU, per così dire. Questo non è un processo banale: comporta molta traduzione dei concetti API in realtà hardware di basso livello, convalida per assicurarsi che la GPU non sia mai impostata su uno stato non valido, conflitto su allocazioni di memoria e dati, tracciamento delle modifiche di stato per emettere il comandi di basso livello corretti e così via. Il driver grafico è responsabile di tutte queste cose.
In DX11 / GL4 e API precedenti, questo lavoro viene in genere svolto da un singolo thread di driver. Anche se si chiama l'API da più thread (cosa che è possibile fare utilizzando elenchi di comandi differiti DX11, ad esempio), si aggiunge solo un po 'di lavoro a una coda per il thread del driver da mordere in seguito. Una grande ragione di ciò è il monitoraggio dello stato che ho citato prima. Molti dei dettagli di configurazione della GPU a livello hardware richiedono la conoscenza dell'attuale stato della pipeline grafica, quindi non c'è un buon modo per suddividere l'elenco dei comandi in blocchi che possono essere elaborati in parallelo: ogni blocco dovrebbe sapere esattamente quale stato dovrebbe iniziare con, anche se il blocco precedente non è stato ancora elaborato.
Questa è una delle grandi cose che sono cambiate in DX12 / Vulkan. Per prima cosa, incorporano quasi tutto lo stato della pipeline grafica in un oggetto, e per un altro (almeno in DX12) quando inizi a creare un elenco di comandi devi fornire uno stato iniziale della pipeline; lo stato non è ereditato da un elenco di comandi al successivo. In linea di principio, ciò consente al driver di non dover sapere nulla sugli elenchi di comandi precedenti prima di poter iniziare la compilazione e che a sua volta consente all'applicazione di suddividere il suo rendering in blocchi parallelizzabili, producendo elenchi di comandi completamente compilati, che possono quindi essere concatenati insieme e inviati alla GPU con un minimo sforzo.
Naturalmente, ci sono molti altri cambiamenti nelle nuove API, ma per quanto riguarda il multithreading, questa è la parte più importante.