Passer au contenu principal
Un exemple de projet intitulé Streaming illustre l’utilisation des API Sampler Feedback pour le streaming de textures. Il utilise les API standard et les API d’extension de Direct3D 12 pour créer des ressources de cartes de retour MinMip et des vues d’accès non ordonné, ainsi que des ressources de cartes 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 une build Windows de bureau. Seule la 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 ultérieure 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 fourni. 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 ultérieure, cette exigence sera assouplie au niveau de fonctionnalité 11_0. La 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 ultérieure. Toutes les fonctionnalités Visual Studio requises proposeront de s’installer 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 release et profile sont beaucoup plus rapides que les builds debug, mais la build debug permet la validation de l’API Direct3D 12 à l’aide de la couche de débogage.

Création et déploiement du contenu de textures

Générez la build release de ContentTool. Exécutez-la 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 avec mipmaps de 8192 × 8192, soit environ 10 Go de contenu. ContentTool consomme une grande quantité de mémoire lors de la création des textures. Nous vous recommandons de l’exécuter sur un système doté d’au moins 16 Go de mémoire. Copiez le contenu de textures 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 la build plateforme Windows universelle (UWP) du devtest Streaming, les fichiers de textures doivent être déployés dans un emplacement de répertoire temporaire du package. Déployez la build UWP de l’application Streaming sans contenu et exécutez-la une fois. L’exemple démarre, affiche un message indiquant que le contenu de textures 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 textures dans un sous-répertoire « streamingtextures » de ce répertoire temporaire. Une fois le contenu correctement déployé, l’exemple doit démarrer et afficher une grille de cubes colorés, comme dans l’image suivante. Capture d'écran de la build UWP de l'exemple Streaming, affichant le contenu de textures généré par ContentTool

Contrôles et utilisation

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

Options et vues de débogage

  1. Les modes de rendu peuvent être parcourus à l’aide de la première option du menu. La complexité du nuanceur de la scène peut être augmentée d’une couche (diffus-normal-spéculaire) à trois couches (trois de chaque diffus-normal-spéculaire). En outre, la carte MinMip peut être superposée à la géométrie de la scène.
  2. Les statistiques de streaming sont activées par défaut et peuvent être basculées dans le menu Streaming Debug Views. Elles incluent des compteurs en temps réel du nombre de vignettes en transit, de la taille virtuelle totale de toutes les textures, de la capacité et de l’occupation du pool de vignettes, des statistiques de latence, des goulots d’étranglement, ainsi que des statistiques de résidence et d’accès par niveau de mip.
  3. Les textures de streaming individuelles peuvent être examinées, y compris la texture principale (ressource en mosaïque) et ses cartes MinMip et cartes de retour MinMip associées. Activez simplement Debug Texture Mode dans le menu Streaming Debug Views, puis utilisez les contrôles de la caméra pour pointer le réticule de visée sur un objet de la scène. Sa texture s’affiche et vous pouvez choisir entre les cartes diffuse, normale ou spéculaire de la première couche.
  4. Les temps processeur des différents sous-systèmes de streaming peuvent être activés dans le menu Streaming Debug Views.

Vue d’ensemble du moteur de streaming

Le moteur de streaming de textures de l’exemple Streaming est conçu pour le streaming de vignettes individuelles de 64 Ko. Les vignettes sont stockées en mémoire dans un pool de vignettes unique (un objet ID3D12Heap) d’une taille de 512 Mo par défaut. Un nombre quelconque de textures en mosaïque peut être instancié dans le moteur de streaming de 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 cartes de retour MinMip associées. Le diagramme suivant représente le cycle d’opérations d’une texture en mosaïque individuelle dans le moteur de streaming de textures. Organigramme représentant le cycle d'opérations, regroupées par travail GPU et processeur, effectuées pour une texture en mosaïque individuelle dans le moteur de streaming de textures Le cycle d’opérations se répète à chaque image. Toutefois, pour une vignette donnée, l’exécution du cycle prend plus d’une image. Notez également que l’implémentation du moteur de streaming est principalement monothread, à l’exception des E/S de fichier asynchrones servant à charger les données des vignettes depuis le 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 streaming, les trois ressources suivantes sont créées.
  1. La texture en mosaïque elle-même, via 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 vignette unique de 64 Ko dans ce format. Par exemple, une texture en mosaïque de 8192 × 8192 au format BC1 donnerait une carte MinMip de 16 × 32 texels, car une vignette de 64 Ko en BC1 a des dimensions de 512 × 256.
  3. Une petite carte de retour MinMip, de 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 retour MinMip à l’aide de l’API ID3D12Device8::CreateSamplerFeedbackUnorderedAccessViewX. Par souci d’efficacité, les cartes de retour 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 via l’API ID3D12Device8::CreatePlacedResource1. Cette stratégie est possible parce que de nombreuses cartes de retour MinMip partagent les mêmes dimensions. Les créer sous forme d’un tableau de textures plus grand garantit la disposition de compactage mémoire la plus efficace pour le matériel, et garantit en outre que les cartes de retour 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 par objet. Lorsque les objets de la 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 streaming vers le tas de descripteurs visible par le GPU du graphe de scène. Lors de la création de la texture en mosaïque, la queue de mip compactée (tous les niveaux de mip inférieurs à la taille de vignette de 64 Ko) est chargée depuis le 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 compacté.

Rendu de la scène et retour d’échantillonneur

Avant le rendu de la scène, toutes les cartes de retour du système sont effacées en bloc avec la valeur maximale possible dans une carte de retour, soit la valeur binaire 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, le retour d’échantillonneur est collecté sur la texture en mosaïque et écrit dans la carte de retour MinMip, sans appliquer la limitation du LOD. Le retour d’échantillonneur est effectué à l’aide d’une fonction du langage HLSL (high-level shader language), FeedbackTexture2D::WriteSamplerFeedback. Les données de retour d’échantillonneur sont très redondantes. La couverture à l’écran d’une vignette 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 la scène n’exécute par défaut que 1/128 (0,7 %) des opérations de retour d’échantillonneur.

Relecture et analyse des données de retour d’échantillonneur

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

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

À chaque image, le moteur de streaming surveille différentes files d’attente pour détecter la fin du chargement et de la décompression des vignettes, ainsi que la fin de leur mappage. Les vignettes 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 via une mise à jour de la carte MinMip. Ces mises à jour sont mises en file d’attente et effectuées dans une copie intermédiaire côté processeur de chaque carte MinMip, puis transférées vers les cartes MinMip lisibles par le GPU via une copie de texture à l’aide de ID3D12GraphicsCommandList::CopyTextureRegion. La liste « Complete Tiles » est également triée par horodatage à chaque image. Toutes les vignettes dont l’horodatage est antérieur à un certain seuil (deux secondes) sont considérées comme expirées et marquées pour être démappées et supprimées. Les vignettes 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 vignettes 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 le streaming de textures. D’autres compromis entre calcul processeur et calcul GPU, entre calcul et empreinte mémoire, et entre précision et résultats visuels perçus conduiraient à des implémentations différentes. Les notes suivantes abordent certains de ces compromis.

Analyse du retour à l’aide du calcul GPU

L’implémentation actuelle utilise la relecture par le processeur des données de retour, analysées par rapport à une base de données des vignettes actuellement connues dans une table de hachage, pour calculer les listes de vignettes à charger en streaming et à faire expirer. Ce travail pourrait également être effectué sur le GPU, en créant une structure de données des vignettes connues adaptée au GPU. Un nuanceur de calcul s’exécuterait à chaque image et comparerait les données de retour à l’ensemble des vignettes actuellement chargées. Le nuanceur de calcul générerait à chaque image des listes de vignettes à charger et à décharger. Le processeur ne travaillerait alors que sur cet ensemble de données considérablement réduit, au lieu d’examiner l’ensemble des données de retour à chaque image.

Résolution de la carte de retour

Les dimensions de la carte de retour peuvent être choisies comme n’importe quelle fraction 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 vignette de 64 Ko, mais cela oblige le travail d’analyse de la carte de retour à évoluer avec le nombre total de vignettes pouvant être mappées dans toutes les ressources, ce qui peut rapidement atteindre des centaines de milliers de vignettes. Choisir des dimensions de carte de retour représentant 2 × 2 vignettes de 64 Ko au mip 0 réduirait le travail d’analyse de 75 %, sans nécessairement affecter beaucoup les résultats visuels.

Partage de la carte de retour entre plusieurs textures en mosaïque

Les nuanceurs de rendu de la scène utilisent trois textures mappées sur les mêmes coordonnées UV : diffuse, normale et spéculaire. Le retour d’échantillonneur capturé sur l’une de ces textures (par exemple, uniquement la carte diffuse) peut facilement être extrapolé pour prendre les mêmes décisions de streaming pour les autres textures de l’ensemble, même si ces autres textures ont des tailles de vignettes ou des dimensions différentes. Ce changement réduirait dans ce cas le travail d’analyse de la carte de retour de 66 %. De plus, les opérations d’E/S sur le disque dur pourraient être optimisées en regroupant les vignettes de l’ensemble de textures, de sorte que le chargement simultané d’une vignette de chacune des textures 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)
Dernière modification le 8 octobre 2026