Skip to main content
Un exemple de projet intitulé Streaming montre l’utilisation des API Sampler Feedback pour la diffusion en continu des textures. Il utilise les API standard et d’extension de Direct3D 12 pour créer des ressources de carte de rétroaction MinMip et des vues d’accès non ordonné, ainsi que des ressources de carte MinMip, des vues de ressources de nuanceur et des échantillonneurs. L’exemple comprend deux builds pour différentes plateformes : Microsoft Game Development Kit (GDK) pour XBOX Series X|S et un build Windows pour ordinateur de bureau. Seul le build XBOX Series X|S utilise les nouvelles API Direct3D 12 de Sampler Feedback. Les autres plateformes émulent Sampler Feedback à l’aide des fonctionnalités Direct3D 12 existantes. Une version future de l’exemple prendra en charge les nouvelles API Sampler Feedback présentes dans la version du printemps 2020 de Windows. Un outil de génération de contenu est également présent; il doit être généré et exécuté sur un PC de bureau pour produire les fichiers de données de textures en mosaïque utilisés dans l’exemple. Pour la version initiale, l’outil de génération de contenu (ContentTool) doit être exécuté sur un PC de bureau équipé d’un GPU de niveau de fonctionnalité Direct3D 12_0. Dans une version future, cette exigence sera assouplie au niveau de fonctionnalité 11_0. Le build de bureau de l’exemple Streaming nécessite un GPU de niveau de fonctionnalité 11_0 prenant en charge les ressources en mosaïque de niveau 2.

Génération de l’exemple Streaming et de l’outil de contenu

Pour générer l’exemple, assurez-vous de disposer d’un environnement de développement Visual Studio 2017 à jour, d’avoir installé le GDK 1911 et d’avoir installé le Windows SDK 17134 ou une version plus récente. Toutes les fonctionnalités Visual Studio requises demanderont à être installées automatiquement à l’ouverture de la solution si elles ne sont pas déjà présentes. Ouvrez la solution (Streaming\Streaming.sln) et régénérez-la. Les builds de version (release) et de profilage sont beaucoup plus rapides que les builds de débogage, mais le build de débogage permet la validation de l’API Direct3D 12 grâce à la couche de débogage.

Création et déploiement du contenu de texture

Générez le build de version (release) de ContentTool. Exécutez-le avec la ligne de commande suivante : contenttool.exe 64 8192 c:\temp Le paramètre « c:\temp » peut être remplacé par tout autre emplacement de répertoire temporaire approprié. Ces options génèrent 64 ensembles diffus-normal-spéculaire de textures en mosaïque de 8192 × 8192 avec mipmaps, pour un total d’environ 10 Go de contenu. ContentTool consomme une grande quantité de mémoire pendant la création des textures. Nous recommandons de l’exécuter sur un système disposant d’au moins 16 Go de mémoire. Copiez le contenu de texture généré par ContentTool (fichiers .trimg et .trdata) dans un sous-répertoire « streamingtextures » de la disposition de l’exemple Streaming, puis déployez. Pour le build plateforme Windows universelle (UWP) du test de développement Streaming, les fichiers de texture doivent être déployés dans un emplacement de répertoire temporaire du package. Déployez le build UWP de l’application Streaming sans contenu et exécutez-le une fois. L’exemple démarre, affiche un message indiquant que le contenu de texture est manquant et ouvre une fenêtre de l’Explorateur de fichiers à un emplacement situé dans le répertoire temporaire de l’application. Copiez les fichiers de données de texture dans un sous-répertoire « streamingtextures » de ce répertoire temporaire. Une fois le contenu déployé avec succès, l’exemple devrait démarrer et afficher une grille de cubes colorés, semblable à l’image suivante. Capture d'écran du build UWP de l'exemple Streaming, affichant le contenu de texture généré par ContentTool

Commandes et utilisation

L’exemple a été conçu pour être utilisé avec une manette XBOX. Pour le build de bureau de l’exemple, nous recommandons de brancher une manette XBOX à votre PC de développement. Si ce n’est pas possible, des commandes au clavier et à la souris sont également offertes, comme le détaille le tableau suivant.

Options et vues de débogage

  1. Les modes de rendu peuvent être alternés au moyen de la première option du menu. La complexité des nuanceurs de la scène peut être augmentée d’une couche (diffus-normal-spéculaire) à trois couches (trois de chaque : diffus-normal-spéculaire). De plus, la carte MinMip peut être superposée à la géométrie de la scène.
  2. Les statistiques de diffusion en continu sont activées par défaut et peuvent être basculées dans le menu Streaming Debug Views. Les statistiques de diffusion en continu comprennent des compteurs en temps réel du nombre de tuiles en transit, de la taille virtuelle totale de toutes les textures, de la capacité et de l’occupation du pool de tuiles, des statistiques de latence, des goulots d’étranglement et des statistiques de résidence/d’accès par niveau de mip.
  3. Les textures diffusées en continu peuvent être examinées individuellement, y compris la texture principale (ressource en mosaïque) et ses cartes MinMip et de rétroaction MinMip associées. Il suffit d’activer Debug Texture Mode dans le menu Streaming Debug Views et d’utiliser les commandes de la caméra pour pointer le réticule de visée sur un objet de la scène. Sa texture est affichée et il est possible de choisir entre les cartes diffuse, normale ou spéculaire de la première couche.
  4. Les temps CPU des différents sous-systèmes de diffusion en continu peuvent être activés dans le menu Streaming Debug Views.

Vue d’ensemble du moteur de diffusion en continu

Le moteur de diffusion en continu des textures de l’exemple Streaming est conçu pour la diffusion de tuiles individuelles de 64 Ko. Les tuiles sont stockées en mémoire dans un pool de tuiles unique (un objet ID3D12Heap) d’une taille de 512 Mo par défaut. N’importe quel nombre de textures en mosaïque peut être instancié dans le moteur de diffusion en continu des textures, la seule limite étant la taille maximale des tas de descripteurs qui suivent les vues de ressources de nuanceur et les vues d’accès non ordonné des ressources de textures en mosaïque et de leurs cartes MinMip et de rétroaction MinMip associées. Le diagramme suivant représente le cycle d’opérations pour une texture en mosaïque individuelle dans le moteur de diffusion en continu des textures. Organigramme représentant le cycle d'opérations, regroupées en travail GPU et CPU, effectuées pour une texture en mosaïque individuelle dans le moteur de diffusion en continu des textures Le cycle d’opérations se répète à chaque image. Toutefois, pour une tuile donnée, l’exécution complète du cycle prend plus d’une image. Notez également que l’implémentation du moteur de diffusion en continu est principalement monothread, à l’exception des E/S de fichiers asynchrones servant à charger les données des tuiles à partir du disque dur. Cette approche maximise la lisibilité et la flexibilité du système. Un multithreading et une optimisation plus poussés réduiraient considérablement la latence, mais rendraient le code plus difficile à comprendre.

Création de textures en mosaïque et configuration du graphe de scène

Lorsqu’une texture en mosaïque est créée dans le moteur de diffusion en continu, les trois ressources suivantes sont créées.
  1. La texture en mosaïque elle-même, au moyen de l’API ID3D12Device::CreateReservedResource.
  2. Une petite carte MinMip, créée en divisant les dimensions de la texture en mosaïque par les dimensions d’une seule tuile de 64 Ko dans ce format. Par exemple, une texture en mosaïque de 8192 × 8192 au format BC1 produirait une carte MinMip de 16 × 32 texels, car une tuile de 64 Ko en BC1 a des dimensions de 512 × 256.
  3. Une petite carte de rétroaction MinMip, ayant les mêmes dimensions que la carte MinMip.
Des descripteurs de vue de ressource de nuanceur (SRV) sont créés pour la texture en mosaïque et la carte MinMip, et un descripteur de vue d’accès non ordonné (UAV) est créé pour la carte de rétroaction MinMip au moyen de l’API ID3D12Device8::CreateSamplerFeedbackUnorderedAccessViewX. Par souci d’efficacité, les cartes de rétroaction MinMip ne sont pas créées en tant que ressources individuelles. Elles sont plutôt créées sous forme de tranches sous-allouées d’une ressource opaque Texture2DArray plus grande, créée au moyen de l’API ID3D12Device8::CreatePlacedResource1. Cette stratégie est possible parce que de nombreuses cartes de rétroaction MinMip partagent les mêmes dimensions. Les créer sous forme d’un tableau de textures plus grand garantit la disposition d’empaquetage mémoire la plus efficace pour le matériel et garantit en outre que les cartes de rétroaction MinMip sont contiguës en mémoire, ce qui permet un effacement et un transcodage en bloc très efficaces. Le graphe de scène contient les descripteurs visibles par le GPU, organisés selon un ordre par objet. Lorsque des objets de scène sont instanciés avec leurs matériaux associés (sélections de textures en mosaïque), les descripteurs sont copiés du tas de descripteurs du moteur de diffusion en continu vers le tas de descripteurs visible par le GPU du graphe de scène. Au moment de la création de la texture en mosaïque, la queue de mips empaquetée (tous les niveaux de mip plus petits que la taille de tuile de 64 Ko) est chargée à partir du disque dur et mappée dans la texture en mosaïque, et la carte MinMip est effacée avec la valeur du premier niveau de mip empaqueté.

Rendu de la scène et rétroaction d’échantillonneur

Avant le rendu de la scène, toutes les cartes de rétroaction du système sont effacées en bloc à la valeur maximale possible dans une carte de rétroaction, soit une valeur binaire de 0xFF, ou 31,875 dans l’encodage fixe non signé 5.3. Pendant le rendu de la scène, la carte MinMip est échantillonnée pour produire une valeur de limitation du niveau de détail (LOD), puis la texture en mosaïque est échantillonnée avec cette valeur de limitation appliquée. Séparément, la rétroaction d’échantillonneur est recueillie sur la texture en mosaïque et écrite dans la carte de rétroaction MinMip, sans que la limitation du LOD soit appliquée. La rétroaction d’échantillonneur est effectuée à l’aide d’une fonction du langage de nuanceur de haut niveau (HLSL), FeedbackTexture2D::WriteSamplerFeedback. Les données de rétroaction d’échantillonneur sont très redondantes. La couverture à l’écran d’une tuile de 64 Ko donnée est assurément assez grande pour les objets raisonnablement proches de la caméra. Par conséquent, le nuanceur de scène n’exécute que 1/128 (0,7 %) des opérations de rétroaction d’échantillonneur par défaut.

Relecture et analyse des données de rétroaction d’échantillonneur

À chaque image, le CPU relit les données de rétroaction d’échantillonneur afin de déterminer quelles tuiles doivent être chargées ensuite. D’abord, le nuanceur de calcul est utilisé pour copier en bloc les données de rétroaction d’échantillonneur depuis les ressources de texture de tableau de rétroaction accessibles en écriture par le GPU vers des empreintes placées lisibles par le CPU. Ensuite, le code CPU parcourt chaque texel des cartes de rétroaction MinMip. Pour chaque texel, la valeur de rétroaction MinMip est comparée à la base de données des tuiles afin de déterminer si la tuile requise pour cet emplacement, à ce niveau de mip, pour cette texture, est présente. Si la tuile n’est pas présente, une entrée de suivi de tuile est créée pour celle-ci et ajoutée à la file « Seen Tiles ». Si la tuile est déjà présente, elle est marquée avec un horodatage courant. Une fois les cartes de rétroaction MinMip traitées, la liste « Seen Tiles » est triée par niveau de LOD, et certaines tuiles sont mises en file d’attente pour être chargées à partir du disque dur, en commençant par les niveaux de LOD les plus grands. Avant le chargement d’une tuile, un stockage temporaire pour les données de tuile compressées doit être alloué, ainsi qu’un emplacement de destination dans le pool de tuiles. La disponibilité du stockage temporaire et du stockage du pool de tuiles est le principal facteur limitant le nombre de tuiles pouvant être chargées simultanément. Après qu’une tuile a été mise en file d’attente pour le chargement, une opération d’E/S de fichier Win32 asynchrone est lancée pour charger la tuile. À la fin de l’opération, plusieurs images plus tard, les données sont décompressées dans un emplacement intermédiaire de décompression. Parallèlement au chargement et à la décompression du fichier, la tuile est également mise en file d’attente pour être mappée dans la ressource en mosaïque sur le GPU au moyen de l’API ID3D12CommandQueue::UpdateTileMappings. Le chargement et le mappage d’une tuile donnée peuvent prendre plusieurs images.

Achèvement des tuiles et expiration jusqu’aux mises à jour de la carte MinMip

À chaque image, le moteur de diffusion en continu surveille diverses files d’attente pour détecter l’achèvement du chargement et de la décompression des tuiles, ainsi que l’achèvement du mappage des tuiles. Les tuiles dont le chargement, la décompression et le mappage sont terminés sont placées dans une liste « Complete Tiles » et sont alors prêtes à être exposées au rendu de la scène au moyen d’une mise à jour de la carte MinMip. Ces mises à jour sont mises en file d’attente et effectuées dans une copie intermédiaire CPU de chaque carte MinMip, puis transférées vers les cartes MinMip lisibles par le GPU au moyen d’une copie de texture à l’aide de ID3D12GraphicsCommandList::CopyTextureRegion. La liste « Complete Tiles » est également triée par horodatage à chaque image. Toute tuile dont l’horodatage est plus ancien qu’un certain seuil (deux secondes) est considérée comme expirée et marquée pour être démappée et supprimée. Les tuiles démappées entraînent également des mises à jour de la carte MinMip, qui sont mises en file d’attente et traitées avec les mises à jour de la carte MinMip pour les tuiles nouvellement chargées.

Fonctionnalités et optimisations non encore implémentées

Cet exemple illustre une seule approche particulière de l’utilisation de Sampler Feedback pour la diffusion en continu des textures. Différents compromis entre calcul CPU et GPU, entre calcul et empreinte mémoire, et entre précision et résultats visuels perçus mèneraient à des implémentations différentes. Les notes suivantes abordent certains de ces compromis.

Analyse de la rétroaction à l’aide du calcul GPU

L’implémentation actuelle utilise la relecture par le CPU des données de rétroaction, analysées par rapport à une base de données des tuiles actuellement connues dans une table de hachage, pour calculer les listes de tuiles à diffuser et à faire expirer. Ce travail pourrait également être effectué sur le GPU, en construisant une structure de données des tuiles connues adaptée au GPU. Un nuanceur de calcul s’exécuterait à chaque image et comparerait les données de rétroaction à l’ensemble de tuiles actuellement chargées. Le nuanceur de calcul générerait à chaque image des listes de tuiles à charger et à décharger. Le CPU ne travaillerait alors que sur cet ensemble de données grandement réduit, plutôt que d’examiner l’ensemble complet des données de rétroaction à chaque image.

Résolution de la carte de rétroaction

Les dimensions de la carte de rétroaction peuvent être choisies comme n’importe quelle fraction en puissance de deux de la taille de la texture en mosaïque (choisie individuellement pour chacune des dimensions U, V, W). Actuellement, l’exemple utilise les dimensions d’une tuile de 64 Ko, mais cela oblige le travail d’analyse de la carte de rétroaction à croître avec le nombre total de tuiles pouvant être mappées dans toutes les ressources, ce qui peut rapidement atteindre des centaines de milliers de tuiles. Choisir des dimensions de carte de rétroaction représentant 2 × 2 tuiles de 64 Ko au mip 0 réduirait le travail d’analyse de 75 % sans nécessairement affecter grandement les résultats visuels.

Partage de la carte de rétroaction entre plusieurs textures en mosaïque

Les nuanceurs de rendu de la scène utilisent trois textures mappées aux mêmes coordonnées UV : diffuse, normale et spéculaire. La rétroaction d’échantillonneur capturée sur l’une de ces textures (c’est-à-dire uniquement la carte diffuse) peut facilement être extrapolée pour prendre les mêmes décisions de diffusion en continu pour les autres textures de l’ensemble, même si ces autres textures ont des tailles de tuile ou des dimensions de texture différentes. Ce changement réduirait le travail d’analyse de la carte de rétroaction de 66 % dans ce cas. De plus, les opérations d’E/S du disque dur pourraient être optimisées en regroupant les tuiles de l’ensemble de textures, de sorte que le chargement simultané d’une tuile de chacune des cartes diffuse, normale et spéculaire puisse se faire en une seule requête d’E/S. Une future mise à jour de l’exemple inclura cette optimisation.

Voir aussi

Vue d’ensemble de Sampler Feedback (préversion)
Last modified on October 6, 2026