Il y a beaucoup de travail à faire sur le CPU pour configurer un cadre pour le GPU, et une bonne partie de ce travail se trouve dans le pilote graphique. Avant DX12 / Vulkan, ce travail de pilote graphique était essentiellement forcé d'être monothread par la conception de l'API.
L'espoir est que DX12 / Vulkan lève cette restriction, permettant au travail du pilote d'être effectué en parallèle sur plusieurs threads CPU dans un cadre. Cela permettra une utilisation plus efficace des processeurs multicœurs, permettant aux moteurs de jeu de pousser des scènes plus complexes sans devenir liés au processeur. C'est l'espoir - si cela se réalisera dans la pratique, c'est quelque chose que nous devrons attendre pour voir au cours des prochaines années.
Pour élaborer un peu: la sortie d'un moteur de rendu est un flux d'appels DX / GL API qui décrivent la séquence d'opérations pour rendre une image. Cependant, il existe une grande distance entre le flux d'appels d'API et les tampons de commandes binaires réels consommés par le matériel GPU. Le pilote doit "compiler" les appels API dans le langage machine du GPU, pour ainsi dire. Ce n'est pas un processus trivial - cela implique beaucoup de traduction des concepts de l'API dans des réalités matérielles de bas niveau, la validation pour s'assurer que le GPU n'est jamais défini dans un état invalide, la gestion des allocations de mémoire et des données, le suivi des changements d'état pour émettre le corriger les commandes de bas niveau, etc. Le pilote graphique est responsable de tout cela.
Dans DX11 / GL4 et les API antérieures, ce travail est généralement effectué par un seul thread de pilote. Même si vous appelez l'API à partir de plusieurs threads (ce que vous pouvez faire en utilisant des listes de commandes différées DX11, par exemple), cela ajoute simplement du travail à une file d'attente pour le thread du pilote à parcourir plus tard. Une grande raison à cela est le suivi de l'état que j'ai mentionné précédemment. La plupart des détails de configuration du GPU au niveau matériel nécessitent la connaissance de l'état actuel du pipeline graphique, donc il n'y a pas de bon moyen de diviser la liste de commandes en morceaux qui peuvent être traités en parallèle - chaque morceau devrait savoir exactement quel état il devrait démarrer. avec, même si le morceau précédent n'a pas encore été traité.
C'est l'une des grandes choses qui ont changé dans DX12 / Vulkan. D'une part, ils incorporent presque tous les états du pipeline graphique dans un objet, et pour un autre (au moins dans DX12) lorsque vous commencez à créer une liste de commandes, vous devez fournir un état initial du pipeline; l'état n'est pas hérité d'une liste de commandes à la suivante. En principe, cela permet au pilote de ne rien savoir des listes de commandes précédentes avant de pouvoir commencer à compiler - et cela à son tour permet à l'application de diviser son rendu en segments parallélisables, produisant des listes de commandes entièrement compilées, qui peuvent ensuite être concaténés ensemble et envoyés au GPU avec un minimum de tracas.
Bien sûr, il y a beaucoup d'autres changements dans les nouvelles API, mais en ce qui concerne le multithreading, c'est la partie la plus importante.