Partager via


Barrières améliorées D3D12

L’interface DDI pour les barrières améliorées est disponible dans Windows 11, version 22H2 WDK (WDDM 3.0). Pour utiliser des barrières améliorées sur 22H2 (ou versions antérieures du système d’exploitation), vous devez installer le KIT SDK Agile 1.706.4-preview.

Les barrières améliorées D3D12 permettent aux développeurs de contrôler indépendamment la synchronisation du travail GPU, les transitions de disposition de texture et le vidage du cache (« accès à la mémoire des ressources »). Cette fonctionnalité offre un ensemble d’API et DDIs Direct3D qui permettent aux développeurs de contrôler indépendamment la synchronisation du travail GPU, les transitions de disposition de texture et le vidage du cache (accès à la mémoire des ressources).

Les barrières améliorées remplacent les barrières de ressources héritées par des types de barrières plus expressifs. La mise à jour offre les fonctionnalités suivantes :

  • Latence de synchronisation réduite.
  • Réduction des vidages excessifs du cache.
  • Pas de mystérieuse promotion et de désintégration règles.
  • Alias de ressources rapides et flexibles (topologies d’alias diverses).
  • Ignorer pendant la transition de barrière.
  • Prise en charge de la lecture/écriture simultanée, y compris la copie de même ressource (auto-copie).
  • Prise en charge des commandes Ignorer, Copier, Résoudre et Effacer asynchrones.

Les barrières améliorées ne sont pas plus simples que les barrières de ressources héritées, mais elles sont beaucoup moins ambiguës et, par conséquent, plus faciles à utiliser pour les développeurs.

Prise en charge améliorée des barrières

La fonctionnalité de barrières améliorées n’est actuellement pas requise pour le matériel ou le pilote. Un pilote indique la prise en charge en définissant le membre EnhancedBarriersSupported de D3D12DDI_D3D12_OPTIONS_DATA_0089 sur TRUE.

  • D3D12DDI_FEATURE_VERSION_VIDEO_0088_0 est le numéro de version qui définit l’implémentation préliminaire des jalons d’obstacles améliorés D3D12 introduits dans Windows 11.

Fonctions de rappel de barrière améliorée D3D12

Les pilotes qui indiquent la prise en charge des obstacles améliorés implémentent les fonctions de rappel suivantes :

Détails de conception

Les pilotes gèrent généralement les barrières de ressources héritées à l’aide de trois opérations distinctes :

  1. Synchronisez le travail gpu.
  2. Effectuez les opérations de vidage du cache nécessaires.
  3. Effectuez les modifications de disposition nécessaires.

Les obstacles améliorés permettent aux développeurs de contrôler chacune de ces opérations séparément.

Types d’obstacles améliorés

Il existe trois types d’obstacles améliorés :

Les barrières à plages remplacent les barrières de ressources héritées. Les barrières à intervalles sont fournies afin que les barrières de ressources héritées puissent être entièrement implémentées sans perte de performances notable.

  • Tous les types de barrière contrôlent la synchronisation du travail GPU et les types d’accès en lecture ou en écriture avant et après la barrière.

  • Les barrières de texture gèrent également la disposition des sous-ressources de texture. La sélection de sous-ressources peut être exprimée sous la forme d’une plage de tranches de mip, de tableau et de plan, en plus de l’option une ou toutes familière utilisée par les barrières de ressources héritées.

  • Les barrières de mémoire tampon et les barrières globales contrôlent uniquement la synchronisation et l’accès aux ressources et n’ont aucun impact sur la disposition des ressources (les mémoires tampons n’ont pas de disposition). Les obstacles globaux affectent toutes les mémoires mises en cache afin qu’elles puissent être coûteuses et ne doivent être utilisées que lorsqu’une barrière plus étendue est insuffisante.

Barrières de texture

  • Contrôlez le vidage du cache, la disposition de la mémoire et la synchronisation pour les sous-ressources de texture.
  • Doit être utilisé uniquement avec des ressources de texture.
  • Autorisez la sélection d’une sous-ressource unique, de toutes les sous-ressources ou d’une plage cohérente de sous-ressources (autrement dit, plage mip et plage de tableaux).
  • Doit fournir un pointeur de ressource non NULL valide.

Barrières de mémoire tampon

  • Contrôler le vidage et la synchronisation du cache pour les ressources de mémoire tampon.
  • Doit être utilisé uniquement avec les ressources de mémoire tampon.
  • Contrairement aux textures, les mémoires tampons n’ont qu’une seule sous-ressource et n’ont pas de disposition qui peut être transférée.
  • Doit fournir un pointeur de ressource non NULL valide.

Obstacles mondiaux

  • Contrôlez le vidage et la synchronisation du cache pour tous les types d’accès aux ressources indiqués dans une file d’attente de commandes unique.
  • N’avez aucun effet sur la disposition de texture.
  • Sont nécessaires pour fournir des fonctionnalités similaires aux barrières D’UAV NULL héritées et aux barrières d’alias NULL/NULL.

Étant donné que les obstacles globaux ne font pas passer la disposition de texture, les obstacles globaux ne peuvent pas être utilisés dans les transitions qui nécessitent autrement une modification de disposition. Par exemple, une barrière globale ne peut pas être utilisée pour passer d’une texture d’accès non simultané de D3D12DDI_BARRIER_ACCESS_RENDER_TARGET à D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE, car cela nécessiterait également un changement de D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET à D3D12DDI_BARRIER_LAYOUT_SHADER_RESOURCE.

Synchronization

Les processeurs graphiques sont conçus pour exécuter autant de travail en parallèle que possible. Tout travail GPU qui dépend du travail GPU précédent doit être synchronisé avant d’accéder aux données dépendantes.

L’interface de barrière améliorée utilise des valeurs SyncBefore et SyncAfter explicites comme masques de champ de bits logiques. Une barrière doit attendre que toutes les étendues SyncBefore de la commande précédente se terminent avant d’exécuter la barrière. De même, une barrière doit bloquer toutes les étendues SyncAfter suivantes jusqu’à ce que la barrière se termine. D3D12DDI_BARRIER_SYNC spécifie l’étendue de synchronisation du gpu en ce qui concerne la barrière.

Pour plus d’informations, consultez la spécification des barrières améliorées.

Transitions de disposition

Les sous-ressources de texture peuvent utiliser différentes dispositions pour différentes méthodes d’accès. Par exemple, les textures sont souvent compressées lorsqu’elles sont utilisées en tant que gabarit de cible de rendu ou de profondeur et sont souvent décompressées pour les commandes de lecture ou de copie du nuanceur. Les barrières de texture utilisent LayoutBefore et LayoutAfter D3D12DDI_BARRIER_LAYOUT valeurs pour décrire les transitions de disposition.

Les transitions de disposition sont uniquement nécessaires pour les textures. Elles sont donc exprimées uniquement dans la structure de données D3D12DDI_TEXTURE_BARRIER .

LayoutBefore et LayoutAfter doivent être compatibles avec le type de file d’attente exécutant la barrière. Par exemple, une file d’attente de calcul ne peut pas faire passer une sous-ressource vers ou hors de D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET.

Pour fournir un ordre de barrière bien défini, la disposition d’une sous-ressource après avoir terminé une séquence de barrières est la dernière DispositionAfter dans la séquence.

Transitions d’accès

Étant donné que de nombreuses opérations d’écriture GPU sont mises en cache, toute barrière d’accès en écriture à un autre accès en écriture ou un accès en lecture seule peut nécessiter un vidage du cache. L’API de barrière améliorée utilise les transitions d’accès pour indiquer que la mémoire d’une sous-ressource doit être rendue visible pour un nouveau type d’accès spécifique. Comme les transitions de disposition, certaines transitions d’accès peuvent ne pas être nécessaires s’il est connu que la mémoire de la sous-ressource associée est déjà accessible pour l’utilisation souhaitée.

Les transitions d’accès sont exprimées comme suit :

  • Pour les textures, dans le cadre de la structure D3D12DDI_TEXTURE_BARRIER.
  • Pour les mémoires tampons, dans le cadre de la structure D3D12DDI_BUFFER_BARRIER.

Les transitions d’accès n’effectuent pas de synchronisation. Il est prévu que la synchronisation entre les accès dépendants soit gérée à l’aide des valeurs SyncBefore et SyncAfter appropriées dans la barrière.

Un AccessBefore rendu visible par un AccessAfter spécifié ne garantit pas que la mémoire des ressources est également visible pour un autre type d’accès. Par exemple :

MyTexBarrier.AccessBefore=D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS;
MyTexBarrier.AccessAfter=D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE;

Cette transition d’accès indique qu’un accès en lecture de nuanceur suivant dépend d’un accès non ordonné-access-write précédent. Toutefois, si le matériel est capable de lire les ressources du nuanceur directement à partir du cache UAV, le pilote risque de ne pas vider le cache UAV.

D3D12DDI_BARRIER_ACCESS_COMMON

D3D12DDI_BARRIER_ACCESS_COMMON est un type d’accès spécial qui indique tout accès compatible avec la disposition. La transition vers D3D12DDI_BARRIER_ACCESS_COMMON signifie que les données de sous-source doivent être disponibles pour tout accès compatible avec la disposition après une barrière. Étant donné que les mémoires tampons n’ont pas de disposition, D3D12DDI_BARRIER_ACCESS_COMMON signifie simplement tout accès compatible avec la mémoire tampon.

La spécification de D3D12DDI_BARRIER_ACCESS_COMMON comme AccessBefore dans une barrière implique l’ensemble de tous les types d’accès en écriture. L’utilisation de D3D12DDI_BARRIER_ACCESS_COMMON comme AccessBefore est déconseillée , car cela peut entraîner des vidages de cache coûteux et inattendus. Au lieu de cela, les développeurs sont encouragés à utiliser uniquement les bits d’accès en écriture les plus étroitement requis pour limiter correctement la surcharge des barrières. Un avertissement de couche de débogage est émis lorsque AccessBefore est défini sur D3D12DDI_BARRIER_ACCESS_COMMON.

Accès simultané à une file d’attente unique

Les obstacles améliorés permettent d’effectuer des opérations simultanées de lecture/écriture sur la même mémoire tampon ou sur la même texture d’accès simultané dans la même file d’attente de commandes.

Les mémoires tampons et les ressources d’accès simultané ont toujours pris en charge l’accès en écriture à partir d’une file d’attente avec des accès en lecture simultanés et non dépendants à partir d’une ou plusieurs autres files d’attente. Cette prise en charge est due au fait que ces ressources utilisent toujours la disposition COMMON et ne présentent aucun risque de lecture/écriture, car les lectures ne doivent pas dépendre des écritures simultanées. (Les règles de barrière de ressource héritées interdisent la combinaison de bits d’état d’écriture avec d’autres bits d’état. Par conséquent, les ressources ne peuvent pas être lues simultanément et écrites dans la même file d’attente à l’aide de barrières de ressources héritées.)

La stratégie one-writer-at-a-time s’applique toujours, car deux régions d’écriture apparemment sans chevauchement peuvent encore avoir des lignes de cache qui se chevauchent.

Plages de sous-ressources

Il est courant pour les développeurs de vouloir migrer une plage de sous-ressources ; par exemple, effectuez une transition d’une chaîne mip complète pour un tableau de texture donné ou un seul niveau mip pour toutes les tranches de tableau. Les obstacles améliorés permettent aux développeurs de passer des plages de sous-ressources logiquement adjacentes à l’aide de la structure D3D12DDI_BARRIER_SUBRESOURCE_RANGE. (Les barrières de transition d’état de ressource héritées fournissent uniquement aux développeurs l’option de transition de tous les états de sous-ressource ou d’un seul état de sous-ressource atomiquement.)

Dispositions de calcul et de file d’attente directes

Les dispositions de barrière améliorées suivantes sont garanties comme étant identiques pour les files d’attente directes et de calcul :

  • D3D12DDI_BARRIER_LAYOUT_GENERIC_READ
  • D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS
  • D3D12DDI_BARRIER_LAYOUT_SHADER_RESOURCE
  • D3D12DDI_BARRIER_LAYOUT_COPY_SOURCE
  • D3D12DDI_BARRIER_LAYOUT_COPY_DEST

Une sous-ressource dans l’une de ces dispositions peut être utilisée dans des files d’attente directes ou des files d’attente de calcul sans transition de disposition.

Sur certains matériels, les barrières de transition de disposition sur les files d’attente directes peuvent être considérablement plus rapides si les accès précédents ou ultérieurs sont également sur des files d’attente directes. Il est fortement recommandé d’accéder aux ressources sur les files d’attente directes à l’aide des dispositions suivantes :

  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE
  • D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST

Les variantes de disposition DIRECT_QUEUE ne sont pas compatibles avec les files d’attente de calcul et ne peuvent pas être utilisées dans les barrières de liste de commandes de calcul. Toutefois, elles sont compatibles avec les opérations de calcul dans les files d’attente directes.

Accès sans barrière

Étant donné qu’il n’y a pas de commandes en attente ou d’opérations de vidage du cache entre les limites d’ExecuteCommandLists, les mémoires tampons peuvent être initialement accessibles dans une étendue ExecuteCommandLists sans barrière. De même, les sous-ressources de texture peuvent également être consultées initialement sans barrière dans les conditions suivantes :

  • La disposition de sous-ressource est compatible avec le type d’accès.
  • Toutes les métadonnées de compression nécessaires ont été initialisées.

Les sous-ressources de texture dans les D3D12DDI_BARRIER_LAYOUT_COMMON de disposition (ou une disposition commune spécifique à la file d’attente telle que D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON) qui n’ont pas d’opérations de lecture ou d’écriture potentiellement en attente sont accessibles dans un flux de commande ExecuteCommandLists sans barrière à l’aide de l’un des types d’accès suivants :

  • D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE
  • D3D12DDI_BARRIER_ACCESS_COPY_SOURCE
  • D3D12DDI_BARRIER_ACCESS_COPY_DEST

En outre, une mémoire tampon ou une texture utilisant une disposition commune spécifique à la file d’attente peut utiliser D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS sans barrière.

Les mémoires tampons et les textures d’accès simultané (textures créées avec l’indicateur D3D12DDI_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS) sont initialement accessibles dans un flux de commande ExecuteCommandLists sans barrière à l’aide de l’un des types d’accès suivants :

  • D3D12DDI_BARRIER_ACCESS_VERTEX_BUFFER
  • D3D12DDI_BARRIER_ACCESS_CONSTANT_BUFFER
  • D3D12DDI_BARRIER_ACCESS_INDEX_BUFFER
  • D3D12DDI_BARRIER_ACCESS_RENDER_TARGET
  • D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS
  • D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE
  • D3D12DDI_BARRIER_ACCESS_STREAM_OUTPUT
  • D3D12DDI_BARRIER_ACCESS_INDIRECT_ARGUMENT
  • D3D12DDI_BARRIER_ACCESS_COPY_DEST
  • D3D12DDI_BARRIER_ACCESS_COPY_SOURCE
  • D3D12DDI_BARRIER_ACCESS_RESOLVE_DEST
  • D3D12DDI_BARRIER_ACCESS_RESOLVE_SOURCE
  • D3D12DDI_BARRIER_ACCESS_PREDICATION

Les accès suivants peuvent également être effectués sans barrière sans aucun type d’accès en écriture. Toutefois, à l’exception de D3D12DDI_BARRIER_ACCESS_RENDER_TARGET, les barrières doivent être utilisées pour vider les écritures séquentielles dans la même ressource.

Copie de ressources autonomes

Bien qu’elles ne soient pas exclusivement liées aux obstacles améliorés, la possibilité d’autoriser les copies d’une région d’une sous-ressource à une autre région non croisée est une fonctionnalité très demandée. Avec des barrières améliorées, une sous-ressource avec une disposition commune peut être utilisée comme source et destination dans le même appel CopyBufferRegion ou CopyTextureRegion. Les copies entre les régions de mémoire source et de destination produisent des résultats non définis. La couche de débogage DOIT être validée par rapport à ces résultats. (La conception de barrière de ressource héritée n’autorise pas une sous-ressource à être à la fois dans l’état D3D12DDI_RESOURCE_STATE_COPY_SOURCE et D3D12DDI_RESOURCE_STATE_COPY_DEST en même temps, et ne peut donc pas copier vers elle-même.)

Initialisation des métadonnées de ressources placées

La conception de la barrière de ressource héritée nécessite l’initialisation des ressources de texture alias nouvellement placées et activées par Clear, Copy ou Discard avant d’être utilisée comme ressource de gabarit de cible de rendu ou de profondeur. Cette exigence est due au fait que les ressources de gabarit de cible et de profondeur de rendu utilisent généralement des métadonnées de compression qui doivent être initialisées pour que les données soient valides. Il en va de même pour les textures réservées avec le mappage de vignettes nouvellement mis à jour.

Les barrières améliorées prennent en charge une option d’abandon dans le cadre d’une barrière. La disposition de barrière passe de D3D12DDI_BARRIER_LAYOUT_UNDEFINED à toute disposition potentiellement compressée (par exemple, D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET, D3D12DDI_BARRIER_LAYOUT_DEPTH_STENCIL, D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS) DOIT initialiser les métadonnées de compression lorsque D3D12DDI_TEXTURE_BARRIER_FLAG_DISCARD est présent dans le membre D3D12DDI_TEXTURE_BARRIER ::Flags.

Outre les ressources de cible et de profondeur/gabarit de rendu, il existe des optimisations de compression de texture UAV similaires que le modèle de barrière hérité n’a pas pris en charge.

Ordre des barrières

Les barrières sont mises en file d’attente dans l’ordre de transfert (ordre d’appel d’API, barrier-group-index, barrier-array-index). Plusieurs barrières sur la même sous-ressource doivent fonctionner comme si les barrières se terminent dans l’ordre mis en file d’attente.

Les barrières mises en file d’attente avec des étendues SyncAfter correspondantes qui peuvent écrire dans la même mémoire doivent effectuer toutes les écritures dans l’ordre mis en file d’attente. Cette exigence évite les courses de données sur les obstacles qui prennent en charge l’alias des ressources. Par exemple, une barrière qui « désactive » une ressource doit vider les caches avant une autre barrière qui « active une ressource différente sur la même mémoire, ce qui permet d’effacer les métadonnées.