Skip to main content
Ce document vise à expliquer l’implémentation des barrières améliorées (Enhanced Barriers) pour XBOX Series X|S et à fournir des exemples détaillés sur la meilleure façon d’en tirer parti. Cette fonctionnalité n’est pas prise en charge sur Durango.

Table des matières

  1. Introduction
  2. Synchronisation du GPU sur XBOX Series X|S
  3. Les barrières en détail
  4. Configuration
  5. Différences avec la spécification PC
  6. Exemples de barrières améliorées
  7. Compatibilité avec les barrières de ressources héritées
  8. Prise en charge dans PIX et validation

Introduction


Les barrières améliorées (EB, Enhanced Barriers) sont un nouvel ensemble d’API D3D12 conçues pour résoudre certains des problèmes introduits par l’API héritée des barrières de ressources (concepts déroutants comme la promotion et la dégradation de l’état des ressources, problèmes de conception liés aux barrières d’aliasing, opérations de vidage excessives, etc.), tout en donnant aux développeurs un contrôle indépendant sur la synchronisation du travail du GPU. Elles offrent un type de barrière plus expressif que ce qui était possible avec les barrières de ressources héritées. Les fonctionnalités des barrières améliorées comprennent :
  • Réduction de la latence de synchronisation et des vidages de cache excessifs.
  • Aucune règle mystérieuse de promotion et de dégradation.
  • Aliasing des ressources rapide et flexible.
  • Abandon (discard) pendant la transition de barrière.
  • Lecture/écriture simultanées et autocopie.
Vous trouverez un lien vers la spécification DirectX des barrières améliorées ici.

Synchronisation du GPU sur XBOX Series X|S


Avant d’aborder les barrières améliorées, une introduction à la synchronisation sur XBOX Series X|S est nécessaire. Il est important de comprendre les concepts et les mécanismes expliqués dans cette section, car ils constituent les éléments de base des barrières. Synchronisation du GPU sur XBOX Series X/S Nous pouvons maintenant plonger dans les barrières améliorées et expliquer plus en détail leur fonctionnement.

Les barrières en détail


Les barrières améliorées introduisent trois concepts utiles pour décider comment effectuer la transition d’une ressource (ou d’une zone mémoire) donnée. Il s’agit de Sync, Access et Layout. D’une certaine façon, ils remplacent le concept précédent d’état de ressource (Resource State) utilisé avec les barrières de ressources. Ils ne sont toutefois pas équivalents, car il est toujours possible d’exprimer un état de ressource comme une combinaison de Sync, Access et Layout, mais il n’est pas toujours possible d’exprimer une combinaison de Sync, Access et Layout comme un état de ressource. La nouvelle API est plus expressive. Sync (avant-après) sert à indiquer au pilote l’étape du pipeline dont il faut attendre la fin, et quel moteur doit être bloqué jusqu’à ce que les opérations de barrière soient terminées.
  • Le tableau suivant montre comment certains indicateurs de synchronisation se traduisent en exigences de vidage (drain) ou de blocage d’étapes (consultez la section sur le pipelining). À noter : certains indicateurs de synchronisation de barrière désignent une étape générale (comme la copie), mais à l’interne, en fonction des données fournies par l’accès et la disposition, ils sont associés à des étapes précises (source de copie/destination de copie), ce qui génère des exigences de vidage/blocage plus adéquates. De plus, le tableau ci-dessous porte sur le cas des textures (pour les tampons, certaines étapes différeraient).
  • Ces exigences sont ensuite analysées et transmises, avec d’autres primitives, aux fonctions SyncBottomOfPipe/SyncTopOfPipe afin de déterminer les actions de synchronisation finales (par exemple D3D12XBOX_SYNC_FLAG_PS_PARTIAL_FLUSH ou D3D12XBOX_SYNC_FLAG_IDLE). Il ne faut pas confondre ces indicateurs avec les indicateurs D3D12_BARRIER_SYNC, qui sont utilisés pour les appels de barrières améliorées.
  • Ces exigences ne connaissent pas les mécanismes qui seront finalement utilisés pour les satisfaire; elles indiquent donc explicitement quel composant matériel doit être vidé/bloqué. Des composants ultérieurs pourraient constater, par exemple, que plusieurs vidages peuvent être accomplis par un seul événement EoP.
Access (avant-après) nous indique avec quels caches cette ressource pourrait interagir avant et après la barrière, ce qui se traduit par des exigences de réécriture (WB) et d’invalidation.
  • Dans le contexte des barrières, il est utile de savoir quelles ressources correspondent à quels caches. Par exemple, si nous avons un AccessBefore de D3D12_ACCESS_RENDER_TARGET et un accès après de D3D12_ACCESS_SHADER_RESOURCE, nous voulons savoir quels caches invalider et/ou vider (si nécessaire). Le tableau suivant présente certains types de ressources fréquemment utilisés et la mémoire qu’ils utilisent.
  • Les types de ressources ne sont pas le seul facteur déterminant quant aux caches utilisés par la ressource. Le type d’opération (scalaire ou vectorielle) compte également, et c’est le compilateur qui en décide. Une lecture dans un tampon de constantes, par exemple, peut passer par le chemin $K-L2 s’il s’agit d’une opération scalaire (SMEM), ou par L0-L1-L2 s’il s’agit d’une opération vectorielle (VMEM).
Layout (avant-après) décrit la disposition en mémoire de la ressource. Cela détermine si les ressources devront être décompressées/compressées lors de l’opération de barrière, ainsi que si une initialisation des métadonnées est nécessaire (pour les cibles de rendu et les tampons de profondeur/gabarit). Par exemple, une cible de rendu avec DCC activée pourrait devoir effectuer un DCC-Eliminate lors de sa transition vers SRV, et donc subir une décompression.
  • Certains indicateurs de ressource et de barrière modifient les exigences de compression/décompression qui en résultent :
    • Le pilote conserve deux tables qui associent le type de ressource aux opérations de compression/décompression. L’une de ces tables concerne les ressources créées avec D3D12XBOX_RESOURCE_FLAG_FORCE_TEXTURE_COMPATIBILITY, tandis que l’autre concerne les ressources non TC.
    • Les EB introduisent D3D12_TEXTURE_BARRIER_FLAG_DISCARD qui, lorsqu’il est passé en argument à la méthode Barrier, force l’initialisation des métadonnées. Avant les EB, cela pouvait se faire au moyen d’une opération d’effacement effectuée avant la première utilisation de la ressource.
    • Les cibles de rendu et les tampons de profondeur/gabarit doivent être créés respectivement avec D3D12_RESOURCE_FLAGS_ALLOW_RENDER_TARGET et D3D12_RESOURCE_FLAGS_ALLOW_DEPTH_STENCIL pour que les surfaces de métadonnées soient allouées correctement.
    • Si vous voulez utiliser la DCC, la ressource doit être créée avec l’indicateur D3D12XBOX_RESOURCE_FLAG_ALLOW_DCC. La DCC impliquera des opérations de décompression lors de la transition d’un état d’écriture à un état de lecture, mais pas si la ressource est aussi créée avec D3D12XBOX_RESOURCE_FLAG_FORCE_TEXTURE_COMPATIBILITY.
  • Le tableau suivant, qui associe les indicateurs de disposition aux indicateurs d’état de compression, aide à mieux comprendre comment les transitions d’entrée et de sortie peuvent entraîner des compressions/décompressions. Par exemple, passer de cible de rendu (rt) à ressource de nuanceur (sr) sur des ressources non TC nécessite une décompression, puisque rt possède plusieurs indicateurs de compression alors que sr est marqué uncompressedAll. Mais la même transition pour une ressource TC ne déclencherait pas de décompression, étant donné que sr possède un surensemble des indicateurs d’état de compression de rt.
Définir un avant et un après pour layout, access et sync nous donne une grande flexibilité pour faire des choses impossibles avec ResourceBarriers (sauf les barrières fractionnées, nous y reviendrons), tout en améliorant les cas où les barrières de ressources pouvaient entraîner des vidages partiels inutiles (barrières UAV) et, dans le pire des cas, mener à une corruption de la mémoire (barrières d’aliasing, lors d’une tentative de décompression sans être certain de la disposition actuelle de la mémoire). Cela correspond aussi mieux à la façon dont la synchronisation fonctionne sur le GPU, ce qui donne au développeur un contrôle plus précis.

La spécification définit également trois types de barrières :

  • Barrières globales :
    • S’appliquent à toute la mémoire. Leur définition ne prend pas de pointeur de ressource.
    • Aucune information de disposition n’est passée en argument.
  • Barrières de tampon
    • Comme leur nom l’indique, les barrières de tampon servent à effectuer la transition des ressources de type tampon.
    • Aucune disposition ni sous-ressource n’est spécifiée en paramètre (puisque les tampons n’utilisent ni l’une ni l’autre).
  • Barrières de texture
    • Transition pour les ressources de texture (cibles de rendu, tampons de profondeur/gabarit, textures SRV, textures UAV, etc.).
    • La disposition est obligatoire; cette barrière peut donc déclencher des décompressions et des compressions.
    • Peut spécifier une sous-ressource précise ou une plage.
      • Pour les sous-ressources, il existe des limites en matière de décompression, puisqu’il est impossible de décompresser seulement une partie d’une ressource.
Voici la définition de l’API D3D12 pour les trois types de barrières :
  • LayoutBefore, LayourAfter : disposition de la mémoire avant et après la barrière. Détermine ce que nous allons compresser/décompresser. Utilisé uniquement par D3D12_TEXTURE_BARRIER.
  • SyncBefore, SyncAfter : étape dont il faut attendre le vidage et étape à bloquer avant de poursuivre.
  • AccessBefore, AccessAfter : indique quels caches nous cesserons d’utiliser et quels caches nous commencerons à utiliser à la suite de la transition.
  • Subresource range — Permet de définir une plage de sous-ressources dont la barrière effectuera la transition. Utilisé uniquement par D3D12_TEXTURE_BARRIER.
  • Resource — Le propriétaire de la mémoire dont nous effectuons la transition. Utilisé par D3D12_TEXTURE_BARRIER et D3D12_BUFFER_BARRIER.
  • Texture Barrier flags — Les valeurs peuvent être D3D12_TEXTURE_BARRIER_FLAG_NONE et D3D12_TEXTURE_BARRIER_FLAG_DISCARD. Utilisé uniquement par D3D12_TEXTURE_BARRIER.
    • Nous utilisons l’indicateur discard lors de l’activation d’une ressource, afin que ses métadonnées soient initialisées correctement.
    • L’utilisation de cet indicateur permet aussi de regrouper l’initialisation des ressources. Les effacements peuvent se chevaucher, et les opérations de synchronisation des barrières sont regroupées.

Configuration


Pour utiliser les barrières améliorées, vous avez besoin des éléments suivants :
  • GDK de mars 2023 ou plus récent.
  • ID3D12GraphicsCommandList7 : nécessaire pour appeler la méthode Barrier. Prend une structure D3D12_BARRIER_GROUP et le numéro de groupe.
(Facultatif) ID3D12Device10 donne accès aux nouvelles définitions de création de ressources : CreatePlacedResource2, CreateCommitedResource3 et CreateReservedResource2. Celles-ci prennent un D3D12_BARRIER_LAYOUT en paramètre au lieu du D3D12_RESOURCE_STATE.
  • Selon la spécification, l’interopérabilité entre les API de barrières améliorées et les D3D12_RESOURCE_STATES hérités est prise en charge. Cependant, les sous-ressources dans tout état hérité autre que D3D12_RESOURCE_STATE_COMMON doivent faire l’objet d’une transition vers D3D12_RESOURCE_STATE_COMMON avant d’être référencées au moyen d’une barrière améliorée.
(Facultatif) ID3D12Device11 donne accès à de nouvelles API d’extension pour la création de ressources : CreatePlacedResourceX1 et CreateComponentPlacedResourceX2. Celles-ci prennent un D3D12_BARRIER_LAYOUT en paramètre au lieu du D3D12_RESOURCE_STATE. Tests avec les barrières de ressources héritées Nous disposons d’un mécanisme permettant de désactiver les EB et de revenir à l’implémentation précédente des barrières de ressources. Si, à un moment donné, les développeurs rencontrent un blocage ou constatent que les barrières se comportent de façon inattendue (par exemple en prenant plus de temps que d’habitude pour une transition donnée, ou en générant de mauvais indicateurs de synchronisation/décompression), il pourrait valoir la peine de revenir en arrière et de vérifier si le problème persiste. Les étapes nécessaires sont les suivantes :
  • Créez un fichier vide dans le dossier Loose (répertoire de déploiement) et nommez-le D3D__DisableLegacyResourceBarrierTranslation.
  • Déployez le jeu et assurez-vous que le fichier a bien été déployé sur la console.
    • Remarque : dans ce mode, le pilote ne prend pas en charge le mélange de barrières héritées et de barrières améliorées.
Nous encourageons fortement les développeurs à communiquer avec nous au moyen des forums des développeurs XBOX s’ils rencontrent de tels problèmes avec les barrières améliorées.

Différences avec la spécification PC


  1. Sur XBOX, le vidage à la frontière d’ExecuteCommandList n’est pas émis; l’accès sans barrière n’est donc pas pris en charge.
  2. Sous-ressources. Sur PC, les métadonnées sont suivies par sous-ressource, alors que ce n’est pas notre cas. Cela signifie que l’état de compression par sous-ressource ne peut pas être suivi. Par conséquent, les changements de disposition qui impliquent une compression ou une décompression donneront des résultats différents selon que la plage de ressources couvre (ou non) la ressource entière.
    • Si une ressource dans une disposition compressée voit une ou plusieurs (mais pas toutes) de ses sous-ressources passer à une disposition non compressée, la ressource entière sera décompressée.
    • Si une ressource dans une disposition non compressée voit une ou plusieurs (mais pas toutes) de ses sous-ressources passer à une disposition compressée, la ressource entière demeure non compressée.
    • Nous prenons en charge des états de compression indépendants pour la profondeur et le gabarit, ce qui signifie que nous pouvons avoir une profondeur compressée et un gabarit non compressé, ou l’inverse.
  3. Les barrières fractionnées fonctionnent, mais elles ne sont pas implémentées comme des barrières fractionnées dans le pilote. Elles sont plutôt converties en barrières immédiates. Nous effectuons cette conversion parce que les barrières fractionnées, telles que définies par D3D12, imposent un coût mémoire par ressource et sont inutilement inefficaces sur notre matériel. Cependant, la conversion en barrières immédiates n’est pas aussi efficace qu’elle pourrait l’être.
    • Cela est dû au fait que le pilote ne reçoit pas d’information complète sur la synchronisation avant et après. La conversion en barrière immédiate se fait du côté proche de la barrière (le côté éloigné est ignoré), de sorte que le pilote doit être pessimiste et bloquer à la fois le CE et le PFP, ce qui peut rendre les barrières fractionnées plus lentes que les barrières nativement immédiates.
    • Par ailleurs, historiquement, très peu de gens utilisent les barrières fractionnées avec l’API héritée.
    • Une façon de résoudre le coût mémoire par ressource à l’avenir pourrait être de permettre aux développeurs de fournir eux-mêmes cette mémoire.
    • Il est prévu de revoir l’implémentation des barrières fractionnées à l’avenir.
Bien qu’il ne s’agisse pas d’une différence, il convient de mentionner que les copies demeurent sérialisées (la spécification mentionne qu’avec les barrières améliorées, les copies sérialisées pourraient ne plus être nécessaires). Remarque : passer D3D12XBOX_CMDLIST_DRIVER_HINT_DONT_SYNC_ON_COPY comme indication de liste de commandes permet des effacements et des copies non sérialisés.
  • Nous recommandons aux utilisateurs d’implémenter leurs propres copies de textures dans des nuanceurs de calcul. Ils devront bien sûr gérer les dépendances, mais cela permettrait un travail non sérialisé et plus efficace.
    • L’une des raisons pour lesquelles les copies de textures gérées par le pilote peuvent être moins performantes est qu’elles peuvent utiliser les caches CB/DB. Cela entraîne la nécessité d’effectuer une réécriture (WB) supplémentaire et d’invalider les caches CB et DB lors des transitions vers les copies de textures ou à partir de celles-ci.

Exemples de barrières améliorées


Bien que des améliorations automatiques des performances à l’exécution puissent être obtenues grâce à la capacité du pilote à traduire les appels de barrières de ressources héritées en équivalents de barrières améliorées, des gains supplémentaires peuvent être réalisés en utilisant directement les barrières améliorées. L’expressivité de l’API offre des occasions de réduire les latences de synchronisation et d’éliminer les vidages inutiles. Les exemples de code suivants montrent comment exprimer des appels de barrières de ressources héritées avec l’API des barrières améliorées afin de profiter de ces avantages supplémentaires.

Barrières de ressources de transition

Dans les applications graphiques, les ressources mémoire sont souvent accédées dans différents contextes, que ce soit en tant que cibles de rendu, vues de ressources de nuanceur, vues de tampons de sommets ou dans d’autres types d’états. Cela explique le besoin fréquent de barrières de ressources de transition pour assurer une synchronisation et une cohérence de cache correctes. Toutefois, dans certains cas, les barrières de ressources de transition peuvent introduire des ralentissements inutiles, comme un vidage excessif du pipeline. Prenons l’extrait de code de barrière de ressource héritée suivant, qui montre la transition de l’état d’une ressource d’une vue de ressource de nuanceur (SRV) à une vue de cible de rendu (RTV) :
Cet exemple dessine d’abord dans une RTV, effectue la transition de la ressource vers une SRV pour une utilisation par un nuanceur de calcul, puis la ramène vers une RTV pour que l’image suivante reproduise le même modèle d’utilisation. Comme il n’existait aucun moyen explicite de décrire comment la ressource a été accédée en dernier et quel type de travail du GPU doit être synchronisé, le pilote doit vider toutes les étapes du pipeline où la ressource aurait pu avoir l’état D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE. Comme on le voit dans la capture PIX ci-dessous, cette transition amène le pilote, comme prévu, à invoquer un vidage partiel du nuanceur de calcul pour tenir compte de la dernière répartition (dispatch), mais déclenche inutilement un vidage partiel du nuanceur de sommets. Cette ressource a été utilisée dans un appel de dessin et une répartition antérieurs, et le pilote ne sait pas dans quel état la ressource a été utilisée dans chaque cas. Il ne sait pas non plus si les dessins et les répartitions sont terminés au moment où la barrière est émise. Ainsi, en donnant la priorité à une synchronisation correcte, il doit supposer que toutes les étapes actives du pipeline autres que le nuanceur de pixels (sommets et calcul) qui utilisent la ressource pourraient être touchées par le changement de type d’accès à la ressource. Interface utilisateur graphique, application Description générée automatiquement Le vidage partiel du nuanceur de sommets coûte 0 µs puisqu’aucun autre dessin n’est en cours d’exécution, comme on le voit dans la capture PIX ci-dessus. Toutefois, la barrière de ressource pourrait prendre plus de temps à se terminer s’il y avait du travail antérieur de nuanceur de sommets provenant d’événements D3D précédents non liés. On peut éviter cela en précisant en plus les états de synchronisation et de disposition de la ressource au moyen de l’API des barrières améliorées, comme l’indiquent les arguments mis en évidence ci-dessous. L’utilisateur peut garantir qu’aucun travail de nuanceur de sommets ne sera actif au moment de l’appel de barrière, et limiter explicitement les vidages partiels à l’étape de calcul, tout en bloquant uniquement le travail qui demande à opérer sur une RTV.
Comme illustré ci-dessous, la barrière améliorée n’utilise plus de vidage partiel du nuanceur de sommets. La vue Command Disassembly et la vue Event Details de PIX peuvent aussi être utilisées pour examiner plus en détail, respectivement, les paquets de commandes et les paramètres de la barrière : Interface utilisateur graphique, texte, application, courriel Description générée automatiquement Interface utilisateur graphique, application, tableau Description générée automatiquement Si la ressource était un tampon plutôt qu’une texture 2D comme dans le cas précédent, et que le tampon devait être utilisé comme sortie de flux (stream output) plutôt que comme RTV, une barrière de tampon pourrait être utilisée de façon similaire :

Barrières de ressources d’accès non ordonné

Les barrières de ressources héritées créées pour synchroniser les lectures et les écritures dans une vue d’accès non ordonné (UAV) sont également sujettes à des vidages superflus du pipeline du GPU, pour des raisons liées au pilote semblables à celles des barrières de ressources de transition héritées. Prenons un scénario où des textures avec mipmaps sont générées par un nuanceur de calcul, toutes écrites et lues dans une UAV de texture, et où le code de barrière de ressource d’accès non ordonné suivant est utilisé pour éviter les risques :
Si l’on examine les événements matériels générés dans PIX, des vidages partiels sont exécutés pour les étapes du nuanceur de pixels, du nuanceur de sommets et du nuanceur de calcul. Seuls des éléments de travail de calcul sont répartis jusqu’à l’exécution de la barrière; des vidages partiels du nuanceur de calcul suffisent donc. Interface utilisateur graphique, application, tableau Description générée automatiquement La solution ici, comme dans l’exemple de barrière de ressource de transition, consiste à utiliser une barrière de texture dont les états de synchronisation vident et bloquent exclusivement le travail du nuanceur de calcul. La modification de code suivante fait disparaître de la capture PIX les vidages partiels des nuanceurs de sommets et de pixels.
Interface utilisateur graphique, application, tableau Description générée automatiquement

Autocopie

Auparavant, il était impossible d’écrire et de lire simultanément une sous-ressource, puisque la conception des barrières de ressources héritées interdit de combiner des bits de lecture seule et d’écriture. Cela signifiait que déplacer des données dans une ressource entre deux régions qui ne se chevauchent pas nécessitait la création d’une texture temporaire, davantage de barrières de transition pour passer de D3D12_RESOURCE_STATE_COPY_SOURCE à D3D12_RESOURCE_STATE_COPY_DEST, et davantage d’opérations de copie de sous-ressources. L’exemple de code ci-dessous illustre le travail nécessaire pour copier le quart supérieur gauche d’une texture dans son quart inférieur droit.
L’API des barrières améliorées permet désormais l’autocopie, ce qui rend le code nécessaire beaucoup plus facile à lire et à écrire tout en éliminant le besoin d’une texture intermédiaire :
La vue Events de PIX peut être utilisée pour visualiser la différence d’événements matériels entre l’implémentation de l’autocopie de texture avec les barrières de ressources héritées et avec les barrières améliorées. Prenons la paire de captures d’écran suivante, tirées de captures PIX, où la première ne contient que des barrières de ressources héritées et la seconde, des barrières améliorées : Tableau Description générée automatiquement Interface utilisateur graphique, texte, application, courriel Description générée automatiquement

Barrières de ressources d’aliasing

Comme on le voit dans le code ci-dessous, tiré de la documentation MSDN publique de D3D12, l’aliasing de ressources placées avec l’API des barrières de ressources héritées consistait historiquement à spécifier uniquement les deux ressources qui partageaient la mémoire du tas. L’API des barrières améliorées peut aider à éviter d’avoir à bloquer tout le travail du GPU et à vider toutes les écritures, tout en fournissant des états de disposition explicites pour que le pilote ne décompresse pas de la mémoire non compressée (consultez ce lien pour en savoir plus sur ce dernier problème, sous « Aliasing Barriers Are Very Expensive »).
Cet extrait de code montre comment les barrières de texture peuvent être utilisées pour faciliter l’aliasing entre deux ressources placées : pTex0 contient des données précédemment copiées depuis un tas de téléversement, et pTex1 réutilise ces données pour les recopier dans un autre tampon.

Compatibilité avec les barrières de ressources héritées


L’API de barrières précédente (Resource Barriers) est toujours prise en charge, mais le pilote les traduit en barrières améliorées en arrière-plan. Plusieurs tests ont été effectués sur des captures PIX pour mesurer l’incidence de la traduction (par rapport à l’utilisation de l’implémentation précédente). Les résultats montrent que la traduction en EB offre des gains importants. Graphique, graphique en courbes Description générée automatiquement Le graphique ci-dessus montre les gains sur des captures d’une seule image (en % d’amélioration du temps d’image) pour un total de 115 captures. Il convient de noter que la sélection comprend à la fois des titres de jeux et des exemples, les exemples affichant les gains les plus élevés. Voici une liste de titres AAA et l’amélioration du temps d’image (%) obtenue à partir de leurs captures PIX. À noter : les gains dépendront grandement de la façon dont le moteur graphique est construit en matière de synchronisation et de placement des barrières. Exemples où la traduction a apporté des améliorations par rapport aux barrières de ressources héritées :

Exemple 1 - Génération de vidages partiels par les barrières UAV

Barrière de ressource héritée Interface utilisateur graphique Barrière de ressource traduite Interface utilisateur graphique La barrière traduite présente les bonnes étapes de synchronisation. Elle effectue des vidages partiels PS, VS et CS avant l’invalidation, puisqu’elle doit se préparer au pire scénario (tenir compte de toutes les étapes qui pourraient écrire dans l’UAV). En revanche, la barrière héritée déclenche un vidage partiel PS et un vidage partiel CS avant l’invalidation. Ce n’est pas correct, puisqu’elle suppose que les étapes VS seront nécessairement suivies d’une étape PS, ce qui n’est pas toujours le cas. Dans cet exemple, les barrières traduites corrigent un problème présent dans les barrières de ressources UAV.

Exemple 2 - Aliasing

Barrière de ressource héritée Interface utilisateur graphique Barrière de ressource traduite Interface utilisateur graphique Dans cet exemple, ResourceBarrier::Aliasing générait des vidages de sortie de flux (streamout) qui n’étaient pas nécessaires. La barrière traduite effectue une attente de clôture (fence) pour certains vidages et invalidations BoP, suivie d’une synchronisation ToP (ce qui est identique à ce que faisait la barrière héritée, sans les paquets liés à la sortie de flux). Dans cet exemple, les barrières traduites obtiennent un gain de performance grâce à la traduction.
Tout ceci montre les gains que les développeurs peuvent obtenir uniquement grâce aux barrières améliorées, sans modifier leur code. Pour voir les gains possibles lors du passage à la nouvelle API Barrier, consultez la section Exemples de barrières améliorées.

Prise en charge dans PIX et validation


PIX prend en charge à la fois les barrières améliorées et les barrières de ressources héritées traduites. Pour les barrières améliorées, un événement PIX nommé Barrier est créé; il contient les paquets CP générés. Image d'une barrière de tampon SRV vers UAV dans PIX Dans la vue Event Details, vous pouvez obtenir tous les détails de l’appel à l’API Barrier, comme les types, le nombre de groupes de barrières, l’avant/après pour la synchronisation, l’accès et la disposition (s’il s’agit d’une barrière de texture), ainsi que pResource (s’il ne s’agit pas d’une barrière globale). Interface utilisateur graphique, texte Description générée automatiquement Pour les barrières de ressources (héritées), PIX affiche le nom de l’API ResourceBarrier et, en tant que nœud enfant, la barrière traduite ([Barrier]). Interface utilisateur graphique, texte, application, site Web Description générée automatiquement Vous pouvez voir les Event Details de la barrière héritée en sélectionnant l’événement ResourceBarrier (c’est la même chose que la vue Event Details des barrières de ressources avant les barrières améliorées, à l’exception des bits Actions qui s’affichent comme D3D12XBOX_RESOURCE_BARRIER_ACTION_NONE). Capture d'écran d'un ordinateur Description générée automatiquement avec un niveau de confiance moyen En sélectionnant le nœud enfant [barrier], vous pouvez voir les Event Details de la barrière traduite (comme pour une barrière améliorée). Interface utilisateur graphique, texte, application Description générée automatiquement

Validation

La validation sera offerte à la fois pour les barrières améliorées et pour les barrières de ressources héritées qui passent par la couche de traduction. La validation obtenue dépendra de l’API utilisée :
  • Pour les barrières améliorées, la parité de validation porte sur les scénarios couverts. Les barrières améliorées sont différentes des barrières de ressources; la validation ne reproduira donc pas exactement ce qu’elle faisait pour l’API héritée, mais garantira que toutes les propriétés avant et après sont correctes pour la transition. Par exemple :
    • S’assurer que les ressources sont dans la bonne disposition au début d’une transition.
    • Valider l’exactitude de l’utilisation de l’API (plus de détails ci-dessous).
  • Pour les barrières de ressources héritées (traduites), la validation offre la parité avec la validation actuelle des barrières de ressources.
La validation vérifie également que les ressources qui passent des barrières héritées aux barrières améliorées sont dans le bon état (D3D12_RESOURCE_STATE_COMMON). Pour la validation de l’API, la spécification énumère ce qui est attendu. La couche de débogage valide les éléments suivants lors des appels Barrier :
  • Le périphérique sous-jacent prend en charge les barrières améliorées
  • Il ne s’agit pas d’une liste de commandes de type bundle
  • Avertissement si un compte (de groupes ou de barrières par groupe) est nul
  • Vérification que les sous-ressources de la barrière de texture correspondent aux limites des sous-ressources de la texture
  • Le type de barrière correspond au type de ressource
  • LayoutBefore et AccessBefore correspondent à la disposition et à l’accès connus ou présumés de la ressource.
  • SyncBefore, AccessBefore et LayoutBefore sont compatibles.
  • SyncAfter, AccessAfter et LayoutAfter sont compatibles.
  • Les barrières de fin de fractionnement correspondent aux barrières de début de fractionnement précédentes.
  • Les barrières fractionnées de tampon et D3D12_BARRIER_LAYOUT_COMMON ne franchissent pas les frontières d’ExecuteCommandLists.
    • Probablement un avertissement plutôt qu’une erreur, en raison des tolérances héritées
Quant à la sortie de validation, elle suivra le schéma ci-dessous :
Last modified on October 6, 2026