Rendu multithreadé ? Mais ça fait plusieurs années que nous sommes équipés de CPU multicores et les développeurs ont fini par s’adapter : multithreader leurs moteurs donc n’a rien de nouveau avec Direct3D 11, allez vous me dire. Pourtant cela vous surprendra peut être mais les moteurs actuels n’utilisent toujours qu’un seul thread pour effectuer le rendu. Les autres threads sont dédiés au son, à la décompression des ressources, à la physique etc… Mais le rendu est pourtant un gros consommateur de temps CPU donc pourquoi ne pas le threader lui aussi ? Il y a plusieurs raisons, certaines liés à la façon dont les GPU fonctionnent, d’autres à l’API 3D. Microsoft s’est donc attaché à résoudre ces dernières et à tenter de contourner les premières.
Tout d’abord threader le rendu semble séduisant au premier abord mais quand on y regarde de plus près on se rend compte qu’il n’y a qu’un seul GPU (et même lorsqu’il y en a plusieurs tout le principe du SLI ou du Crossfire est de donner l’illusion qu’il n’y a qu’un GPU virtuel) et par conséquent un seul buffer de commandes. Qui dit ressource unique partagée par plusieurs threads dit donc mutex afin d’empêcher plusieurs threads d’écrire des commandes simultanément, se marchant sur les pieds ! Tous les bénéfices d’utiliser plusieurs threads sont donc annulés par cette section critique qui serialise tout le code. Aucune API ne peut résoudre ce problème inhérent à la façon dont communiquent le CPU et le GPU, mais Microsoft a proposé une API pour essayer de le contourner. Direct3D 11 introduit ainsi des buffers de commandes annexes qui peuvent être sauvegardés pour être utilisés ensuite.
Chaque thread dispose donc d’un contexte différé, les commandes qui y sont écrites sont enregistrées dans une liste d’affichage qui peut ensuite être insérée dans le flux de commande principal. Evidemment il faut toujours s’assurer lorsqu’une liste d’affichage est appelée par le thread principal (le « Execute » du schéma ci-dessus) que son thread a terminé de la remplir. Il y a donc toujours une synchronisation mais ce modèle d’exécution permet au moins de paralléliser une partie du travail de rendu même si l’accélération ne peut pas être idéale.
Un autre problème des versions précédentes de Direct3D concernait la création des ressources comme par exemple les textures. Dans les versions actuelles de l’API (9 comme 10) la création des ressources devait se faire dans le thread de rendu. Les développeurs contournaient le problème en créant un thread qui lisait et décompressait la texture depuis le disque par exemple et remplissait la ressource (l’object direct3D) qui était lui créé sur le thread principal.
Mais comme on le voit une part importante du travail restait à la charge du thread principal déjà surchargé ce qui ne garantissait pas une bon équilibre et donc un bon temps d’exécution. Microsoft introduit donc une nouvelle interface avec Direct3D 11 : un programmeur peut créer un objet device par thread qui sera utilisé pour le chargement des ressources. La synchronisation au sein des fonctions d’un device est géré plus finement que dans Direct3D 10 et est beaucoup plus économe en temps CPU.



