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.
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
- 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.
- 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.
- 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.
- 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.
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.- La texture en mosaïque elle-même, au moyen de l’API
ID3D12Device::CreateReservedResource. - 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.
- Une petite carte de rétroaction MinMip, ayant les mêmes dimensions que la carte MinMip.
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’APIID3D12CommandQueue::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 deID3D12GraphicsCommandList::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.
