Vue d’ensemble de la liaison de ressources
Les clés pour comprendre la liaison de ressources dans DirectX 12 sont les concepts des descripteurs, des tables de descripteurs, des tas de descripteurs et des signatures racines.
Ressources et pipeline graphique
Les ressources de nuanceur (telles que les textures, les tables constantes, les images, les mémoires tampons, et ainsi de suite) ne sont pas liées directement au pipeline du nuanceur ; au lieu de cela, ils sont référencés via un descripteur. Un descripteur est un petit objet qui contient des informations sur une ressource.
Les descripteurs sont regroupés pour former des tables de descripteurs. Chaque table de descripteur stocke des informations sur une plage de types de ressources. Il existe de nombreux types de ressources différents. Les ressources les plus courantes sont les suivantes :
- Vues tampons constantes (CBV)
- Vues d’accès non ordonnées (UAV)
- Affichages de ressources du nuanceur (SVS)
- Échantillonneurs
Les descripteurs SRV, UAV et CBV peuvent être combinés dans la même table de descripteur.
Les graphiques et les pipelines de calcul accèdent aux ressources en référençant des tables de descripteurs par index.
Les tables de descripteurs sont stockées dans un tas de descripteurs. Les tas de descripteurs contiennent idéalement tous les descripteurs (dans les tables de descripteurs) pour qu’une ou plusieurs images soient rendues. Toutes les ressources seront stockées dans des tas en mode utilisateur.
Un autre concept est celui d’une signature racine. La signature racine est une convention de liaison, définie par l’application, qui est utilisée par les nuanceurs pour localiser les ressources auxquelles ils doivent accéder. La signature racine peut stocker :
- Indexe les tables de descripteurs dans un tas de descripteur, où la disposition de la table de descripteur a été prédéfinie.
- Constantes, de sorte que les applications peuvent lier des constantes définies par l’utilisateur ( appelées constantes racines) directement à des nuanceurs sans avoir à passer par des descripteurs et des tables de descripteurs.
- Un très petit nombre de descripteurs directement à l’intérieur de la signature racine, comme une vue tampon constante (CBV) qui change par dessin, ce qui évite à l’application de devoir placer ces descripteurs dans un tas de descripteurs.
En d’autres termes, la signature racine fournit des optimisations des performances adaptées aux petites quantités de données qui changent par tirage.
La conception de Direct3D 12 pour la liaison la sépare d’autres tâches, telles que la gestion de la mémoire, la gestion de la durée de vie des objets, le suivi d’état et la synchronisation de la mémoire (reportez-vous à Différences dans le modèle de liaison de Direct3D 11). La liaison Direct3D 12 est conçue pour être faible et optimisée pour les appels d’API qui sont effectués le plus fréquemment. Il est également évolutif entre le matériel bas de gamme et le haut de gamme, et évolutif des anciennes (pipeline Direct3D 11 plus linéaire) aux approches plus récentes (plus parallèles) de la programmation du moteur graphique.
Types de ressources et affichages
Les types de ressources sont les mêmes que Direct3D 11, à savoir :
- Texture1D et Texture1DArray
- Texture2D et Texture2DArray, Texture2DMS, Texture2DMSArray
- Texture3D
- Mémoires tampons (typées, structurées et brutes)
Les vues de ressources sont similaires, mais légèrement différentes de Direct3D 11, les vues de vertex et de mémoire tampon d’index ont été ajoutées.
- Affichage des mémoires tampons de constantes (CBV)
- Vue d’accès non ordonné (UAV)
- Vue des ressources du nuanceur (SRV)
- Échantillonneurs
- Affichage cible de rendu (RTV)
- Vue gabarit de profondeur (DSV)
- Affichage mémoire tampon d’index (IBV)
- Vue tampon de vertex (VBV)
- Mode de sortie de flux (SOV)
Seules les quatre premières de ces vues sont réellement visibles par les nuanceurs. Reportez-vous aux tas de descripteurs visibles du nuanceur et Aux tas de descripteurs visibles non nuanceurs.
Flux de contrôle de liaison de ressources
Se concentrant uniquement sur les signatures racines, les descripteurs racine, les constantes racines, les tables de descripteurs et les tas de descripteurs, le flux de la logique de rendu pour une application doit être similaire à ce qui suit :
- Créez un ou plusieurs objets de signature racine, un pour chaque configuration de liaison différente dont une application a besoin.
- Créez des nuanceurs et un état de pipeline avec les objets de signature racine avec lesquels ils seront utilisés.
- Créez un (ou, si nécessaire, plusieurs) tas de descripteurs qui contiennent tous les descripteurs SRV, UAV et CBV pour chaque image de rendu.
- Initialisez le ou les tas de descripteurs avec des descripteurs si possible pour des ensembles de descripteurs qui seront réutilisés sur de nombreuses images.
- Pour chaque image à afficher :
- Pour chaque liste de commandes :
- Définissez la signature racine actuelle à utiliser (et modifiez si nécessaire pendant le rendu, ce qui est rarement requis).
- Mettez à jour les constantes de signature racine et/ou les descripteurs de signature racine pour la nouvelle vue (par exemple, les projections world/view).
- Pour chaque élément à dessiner :
- Définissez tous les nouveaux descripteurs dans les tas de descripteurs en fonction des besoins pour le rendu par objet. Pour les tas de descripteurs visibles par le nuanceur, l’application doit s’assurer d’utiliser l’espace du tas de descripteur qui n’est pas déjà référencé par le rendu qui peut être en vol, par exemple, en allouant linéairement de l’espace via le tas de descripteur pendant le rendu.
- Mettez à jour la signature racine avec des pointeurs vers les régions requises des tas de descripteurs. Par exemple, une table de descripteur peut pointer vers certains descripteurs statiques (immuables) initialisés précédemment, tandis qu’une autre table de descripteurs peut pointer vers certains descripteurs dynamiques configurés pour le rendu actuel.
- Mettez à jour les constantes de signature racine et/ou les descripteurs de signature racine pour le rendu par élément.
- Définissez l’état du pipeline pour l’élément à dessiner (uniquement si la modification est nécessaire), compatible avec la signature racine actuellement liée.
- Dessin
- Répéter (élément suivant)
- Répéter (liste de commandes suivante)
- Strictement lorsque le GPU a terminé avec toute mémoire qui ne sera plus utilisée, il peut être libéré. Les références à ces descripteurs n’ont pas besoin d’être supprimées si un rendu supplémentaire qui utilise ces descripteurs n’est pas envoyé. Ainsi, le rendu suivant peut pointer vers d’autres zones dans les tas de descripteurs, ou les descripteurs obsolètes peuvent être remplacés par des descripteurs valides pour réutiliser l’espace du tas de descripteur.
- Pour chaque liste de commandes :
- Répéter (image suivante)
Notez que les autres types de descripteurs, les vues cibles de rendu (RTV), les vues de gabarit de profondeur (DSV), les vues de mémoire tampon d’index (IBV), les vues de mémoire tampon de vertex (VBV) et les vues de sortie de flux (SOV) sont gérées différemment. Le pilote gère le contrôle de version de l’ensemble de descripteurs liés pour chaque dessin lors de l’enregistrement de la liste de commandes (de la même manière que les liaisons de signature racine sont gérées par le matériel/pilote). Cela diffère du contenu des tas de descripteurs visibles par le nuanceur, pour lesquels l’application doit allouer manuellement via le tas, car elle référence différents descripteurs entre les dessins. Le contrôle de version du contenu du tas visible par le nuanceur est laissé à l’application, car il permet aux applications de réutiliser des descripteurs qui ne changent pas, ou d’utiliser de grands ensembles statiques de descripteurs et d’utiliser l’indexation du nuanceur (par exemple, par ID de matériau) pour sélectionner des descripteurs à utiliser à partir du tas de descripteur, ou utiliser des combinaisons de techniques pour différents ensembles de descripteurs. Le matériel n’est pas équipé pour gérer ce type de flexibilité pour les autres types de descripteurs (RTV, DSV, IBV, VBV, SOV).
Sous-allocation
Dans Direct3D 12, l’application a un contrôle de bas niveau sur la gestion de la mémoire. Dans les versions antérieures de Direct3D, y compris Direct3D 11, il y avait une allocation par ressource. Dans Direct3D 12, l’application peut utiliser l’API pour allouer un bloc de mémoire volumineux, plus grand que n’importe quel objet unique. Une fois cette opération effectuée, l’application peut créer des descripteurs pour pointer vers des sections de ce bloc de mémoire volumineux. Ce processus de décision de l’emplacement à placer (blocs plus petits à l’intérieur du grand bloc) est appelé sous-allocation. L’activation de l’application peut générer des gains dans l’utilisation efficace du calcul et de la mémoire. Par exemple, le renommage des ressources est rendu obsolète. À la place de cela, les applications peuvent utiliser des clôtures pour déterminer quand une ressource particulière est utilisée et quand ce n’est pas en mettant en place des clôtures sur les exécutions de liste de commandes où la liste de commandes nécessite l’utilisation de cette ressource particulière.
Libérer des ressources
Avant que toute mémoire liée au pipeline puisse être libérée, le GPU doit en avoir terminé.
Attendre le rendu des images est probablement la façon la plus grossière d’être certain que le GPU est terminé. À un grain plus fin, vous pouvez à nouveau utiliser des clôtures : lorsqu’une commande est enregistrée dans une liste de commandes dont vous souhaitez suivre l’achèvement, insérez une clôture immédiatement après celle-ci. Ensuite, vous pouvez effectuer différentes opérations de synchronisation avec la clôture. Vous envoyez un nouveau travail (listes de commandes) qui attend qu’une clôture spécifiée soit passée sur le GPU, ce qui indique que tout est terminé avant qu’il soit terminé, ou vous pouvez demander qu’un événement de processeur soit déclenché lorsque la clôture est passée (que l’application peut attendre avec un thread en veille). Dans Direct3D 11, il s’agissait EnqueueSetEvent
de ().