Vue d’ensemble des tas de descripteurs

Les segments de mémoire de descripteur contiennent de nombreux types d’objets qui ne font pas partie d’un objet d’état de pipeline (PSO), tels que les vues de ressources de nuanceur (SRVs), les vues d’accès non ordonnées (UMV), les vues de mémoire tampon constante (CBV) et les échantillonneurs.

Objectif des segments de mémoire de descripteur

L’objectif principal d’un tas de descripteurs est d’englober la majeure partie de l’allocation de mémoire requise pour stocker les spécifications de descripteur des types d’objets référencés par les nuanceurs pour une fenêtre de rendu aussi grande que possible (idéalement, un cadre entier de rendu ou plus). Si une application change les textures que le pipeline voit rapidement à partir de l’API, il doit y avoir de l’espace dans le tas de descripteur pour définir des tables de descripteur à la volée pour chaque ensemble d’état nécessaire. L’application peut choisir de réutiliser des définitions si les ressources sont utilisées à nouveau dans un autre objet, par exemple, ou simplement affecter l’espace du tas de manière séquentielle lorsqu’il change différents types d’objets.

Les segments de mémoire de descripteur permettent également aux composants logiciels individuels de gérer le stockage de descripteur séparément les uns des autres.

Tous les tas sont visibles par l’UC. L’application peut également demander quelles propriétés d’accès au processeur un tas de descripteur doit avoir (le cas échéant) : écriture combinée, écriture différée, et ainsi de suite. Les applications peuvent créer autant de tas de descripteurs que vous le souhaitez avec les propriétés souhaitées. Les applications ont toujours la possibilité de créer des segments de mémoire de descripteur qui sont purement destinés à des fins intermédiaires qui ne sont pas contraintes de taille et qui sont copiés dans des segments de mémoire de descripteur utilisés pour le rendu si nécessaire.

Il existe certaines restrictions dans ce qui peut aller dans le même tas de descripteur. Les entrées CBV, UAV et SRV peuvent se trouver dans le même tas de descripteur. Toutefois, les entrées samplers ne peuvent pas partager un tas avec des entrées CBV, UAV ou SRV. En règle générale, il existe deux ensembles de segments de mémoire de descripteur, un pour les ressources courantes et le second pour samplers.

L’utilisation des segments de mémoire de descripteur par Direct3D 12 reflète ce que fait la plupart du matériel GPU, ce qui consiste à exiger que les descripteurs ne vivent que dans les segments de mémoire de descripteur, ou simplement que moins de bits d’adressage sont nécessaires si ces segments de mémoire sont utilisés. Direct3D 12 nécessite l’utilisation de segments de mémoire de descripteur, il n’existe aucune option permettant de placer des descripteurs n’importe où dans la mémoire.

Les segments de mémoire de descripteur ne peuvent être modifiés que immédiatement par l’UC, il n’existe aucune option pour modifier un tas de descripteur par le GPU.

Synchronization

Le contenu du tas de descripteur peut être modifié avant, pendant et après l’enregistrement des listes de commandes qui le référencent. Toutefois, les descripteurs ne peuvent pas être modifiés alors qu’une liste de commandes envoyée pour l’exécution peut référencer cet emplacement, car cela peut appeler une condition de concurrence.

Liaison

Au plus un tas combiné CBV/SRV/UAV et un tas sampler peuvent être liés à tout moment. Ces segments de mémoire sont partagés entre les pipelines graphiques et de calcul (décrits dans leurs psO).

Changement de segments de mémoire

Il est acceptable qu’une application change de segments de mémoire dans la même liste de commandes ou dans différentes à l’aide des API SetDescriptorHeaps et Reset . Sur certains matériels, cela peut être une opération coûteuse, nécessitant un blocage gpu pour vider tout le travail qui dépend du tas de descripteur actuellement lié. Par conséquent, si les segments de mémoire de descripteur doivent être modifiés, les applications doivent essayer de le faire lorsque la charge de travail GPU est relativement légère, ce qui peut limiter les modifications au début d’une liste de commandes.

Paquets

Avec les bundles, il ne peut y avoir qu’un seul appel à la méthode SetDescriptorHeaps , et le jeu de segments de mémoire de descripteur doit correspondre exactement à ceux de la liste de commandes appelant le bundle. Si le bundle ne modifie pas les tables de descripteur, il n’est pas nécessaire de définir les segments de mémoire de descripteur.

Pour obtenir la liste des appels d’API qui ne peuvent pas être utilisés avec des bundles, reportez-vous à La création et à l’enregistrement de listes de commandes et de bundles.

Gestion

Pour afficher tous les objets d’une scène, de nombreux descripteurs seront nécessaires et il existe différentes stratégies de gestion qui peuvent être suivies.

La stratégie la plus basique consisterait à remplir une nouvelle zone du tas de descripteur avec toutes les exigences pour l’appel de tirage suivant. Par conséquent, juste avant d’émettre l’appel de dessin sur la liste de commandes, un pointeur de table de descripteur est défini sur le début de la table fraîchement remplie. L’avantage est qu’il n’est pas nécessaire d’enregistrer où n’importe quel descripteur particulier se trouve dans le tas.

L’inconvénient de cette stratégie est qu’il pourrait y avoir beaucoup de répétition de descripteurs dans le tas de descripteur, en particulier lorsqu’une scène très similaire est rendue, et que l’espace du tas de descripteur va être utilisé rapidement. Les segments de mémoire de descripteur distincts pour ceux qui sont rendus sur le GPU et ceux enregistrés par l’UC seraient probablement nécessaires pour éviter les conflits. Vous pouvez également utiliser un système de sous-allocation.

En outre, le système de base peut être optimisé en utilisant soigneusement les tables de descripteur qui se chevauchent d’un appel de tirage à l’autre, afin que seuls les nouveaux descripteurs requis soient ajoutés.

Une stratégie plus efficace que la stratégie de base consisterait à pré-remplir les tas de descripteurs avec des descripteurs requis pour les objets (ou matériaux) connus pour faire partie de la scène. L’idée ici est qu’il n’est nécessaire de définir la table de descripteur au moment du dessin, car le tas de descripteur est rempli à l’avance.

Une variante de la stratégie de pré-remplissage consiste à traiter le tas de descripteur comme un tableau énorme, contenant tous les descripteurs requis dans des emplacements connus fixes. Ensuite, l’appel de dessin doit uniquement recevoir un ensemble de constantes qui sont les index dans le tableau de l’endroit où les descripteurs doivent être utilisés.

Une optimisation supplémentaire consiste à garantir que les constantes racine et les descripteurs racines contiennent celles qui changent le plus fréquemment, plutôt que de placer des constantes dans le tas de descripteur. Pour la plupart des matériels, il s’agit d’un moyen efficace de gérer les constantes.

Dans la pratique, un moteur graphique peut utiliser une stratégie différente dans différentes situations et combiner des éléments de chaque stratégie pour répondre aux exigences de dessin particulières.

Tas de descripteurs