- Philosophie de conception
- Objets de l’API XG Memory
- Procédure pas à pas et exemples d’utilisation de XG Memory
- Conclusion
Philosophie de conception
Fondamentalement, XG Memory est une solution permettant de mapper des pages de mémoire physique (pages système et pages ESRAM) vers une plage d’adresses virtuelles. Le système d’exploitation des titres et la pile de pilotes graphiques du Microsoft Game Development Kit (GDK) fournissent des API de bas niveau telles que XMemVirtualAlloc et XMemAllocatePhysicalPages pour effectuer ces opérations, mais elles peuvent être difficiles à utiliser efficacement. XG Memory est construite au-dessus de ces API de bas niveau et a été conçue selon les principes suivants.- Fournir une API de haut niveau et facile à utiliser que tous les titres peuvent adopter pour le développement D3D12.X, voire D3D11.X. Parallèlement, livrer le code source afin que la complexité sous-jacente puisse être examinée et améliorée si nécessaire.
- Concevoir en tenant compte de la prise en charge des dispositions de mémoire dynamiques. Les titres modernes adoptent de plus en plus la résolution dynamique et d’autres techniques qui nécessitent de fréquents remappages des dispositions de mémoire au moment de l’exécution.
- Concevoir en tenant compte de la prise en charge d’un remappage facile de la mémoire au sein d’une même image. Une utilisation efficace de l’ESRAM nécessite des stratégies dans lesquelles différentes ressources peuvent partager les mêmes pages de mémoire si elles ne sont pas utilisées en même temps.
- Veiller à ce que l’aliasing de mémoire et l’aliasing de données entre les ressources soient mieux délimités pour faciliter l’outillage. L’aliasing de mémoire se produit lorsque deux ressources partagent la même mémoire, mais que les données qu’elle contient ne sont jamais vues simultanément par les deux ressources à des fins de réinterprétation. L’aliasing de données se produit lorsque deux ressources partagent la même mémoire avec l’intention de réinterpréter les données qu’elle contient de deux manières différentes.
Objets de l’API XG Memory
L’API XG Memory comporte trois objets d’API : le moteur, la disposition et le mappage.- Le moteur (classe XGMemoryLayoutEngine) est un objet qui représente le budget mémoire que vous attribuez à une ou plusieurs dispositions de mémoire. Il stocke une liste de pages physiques d’ESRAM et/ou de mémoire système qui seront mappées vers les dispositions. C’est également là que les objets de disposition sont créés.
- La disposition (classe XGMemoryLayout) est un objet qui représente une disposition de mémoire unique, composée d’une plage d’adresses virtuelles réservée et de plusieurs mappages à l’intérieur de celle-ci. Bien que chaque moteur puisse créer autant de dispositions que vous le souhaitez, une seule disposition de chaque moteur doit être utilisée à un moment donné. Les dispositions d’un même moteur partagent les mêmes pages de mémoire physique.
- Le mappage (structure XGMemoryLayoutMapping) représente un mappage unique d’un ensemble de pages physiques vers une plage d’adresses virtuelles au sein d’une disposition. Une fois qu’un mappage est construit, une ou plusieurs ressources graphiques peuvent être créées par placement à l’adresse virtuelle du mappage.
Procédure pas à pas et exemples d’utilisation de XG Memory
Préparation à l’utilisation de XG Memory
Avant de commencer à utiliser XG Memory, réfléchissez à votre titre et à la place que XG Memory pourrait y occuper. Avez-vous seulement une ou deux ressources qui doivent utiliser l’ESRAM ? Avez-vous un sous-système entier qui doit réduire son empreinte mémoire grâce au partage ? Pouvez-vous configurer toutes les cibles de rendu de votre moteur au même endroit ? XG Memory devient plus utile à mesure que davantage de ressources sont placées dans la même disposition et que davantage d’opportunités de partage de mémoire apparaissent. La conception des dispositions de XG Memory convient également mieux aux moteurs dans lesquels les ressources de cibles de rendu sont configurées en série (sous forme d’une suite séquentielle d’étapes sur le même thread).Étape 1 : créer un moteur de disposition XG Memory
Pour commencer, créez un moteur contenant la quantité maximale de mémoire physique que vous souhaitez utiliser pour toutes les ressources qui seront créées à l’aide de XG Memory. Par exemple, vous pouvez créer un moteur avec 32 Mo (512 pages) d’ESRAM et 64 Mo (1 024 pages) supplémentaires de mémoire système. Lors de la création du moteur, vous pouvez soit transmettre une liste préallouée de numéros de pages physiques provenant de XMemAllocatePhysicalPages, soit demander à XG Memory d’appeler XMemAllocatePhysicalPages à votre place. Les numéros de pages ESRAM peuvent être générés trivialement en utilisant les indices 0 à 511 pour désigner les 512 pages de 64 Ko qui composent l’intégralité de l’ESRAM.Étape 2 : créer une disposition XG Memory
Ensuite, déterminez la taille virtuelle totale de toutes les ressources que vous prévoyez de configurer, y compris le partage (c’est-à-dire en comptant deux fois les chevauchements). Par exemple, nous pouvons créer une disposition avec 128 Mo d’espace d’adressage virtuel pour couvrir environ 10 cibles 1080p de 32 bpp, plus une petite marge. Ce nombre peut être surestimé avec très peu de pénalité, car la création d’une disposition se contente de réserver de l’espace d’adressage virtuel. La réservation d’espace d’adressage virtuel est très peu coûteuse, et vous disposez de centaines de Go d’espace d’adressage virtuel. La réservation d’adresses virtuelles s’effectue en appelant XMemVirtualAlloc avec MEM_RESERVE. En plus de réserver de l’espace d’adressage virtuel, la disposition contient des listes libres de pages de mémoire physique obtenues auprès du moteur. Lors de la création des mappages, les pages sont prélevées dans la liste libre selon le principe dernier entré, premier sorti (LIFO).Étape 3 : créer des mappages et des ressources placées
Pour chaque ressource que vous souhaitez configurer, déterminez la taille de la ressource dans l’espace d’adressage virtuel à l’aide de la bibliothèque XG, puis arrondissez au supérieur et divisez pour obtenir un nombre de pages de 64 Ko. La classe de disposition XG Memory dispose de plusieurs méthodes de création de mappages, mais elles partagent toutes un concept commun. Pour chaque mappage, vous spécifiez un nombre de pages ESRAM et un nombre de pages de mémoire système à utiliser lors de la validation des pages physiques dans le mappage. Les différentes API de création de mappages ne diffèrent que par la complexité du modèle de mappage à générer (l’ordre spécifique des pages ESRAM et système dans le mappage). En interne, XG Memory utilise une combinaison de XMemMapPhysicalPages et de D3DMapEsramPages pour valider respectivement les pages système et ESRAM dans l’espace d’adressage virtuel réservé de la disposition. Une fois qu’un mappage est créé, vous pouvez utiliser le membre MappingBaseAddress de la structure XGMemoryLayoutMapping comme entrée d’une API de création de ressources placées, telle que ID3D12Device::CreatePlacedResourceX. N’oubliez pas que les adresses virtuelles graphiques sur XBOX One sont uniformes entre le processeur et le GPU ; vous pouvez donc convertir une valeur d’adresse UINT64 en void* ou inversement.Étape 4 (facultative) : abandonner des mappages pour réutiliser des pages physiques
Si vous souhaitez partager des pages entre deux ressources ou plus, vous pouvez abandonner (relinquish) un mappage afin de remettre ses pages physiques dans la liste libre de la disposition. Notez que l’opération d’abandon ne libère pas la mémoire validée du mappage. Elle permet de réaffecter les pages validées pour ce mappage à de nouveaux mappages. Par conséquent, après avoir abandonné un mappage, vous ne pouvez plus utiliser la mémoire de ce mappage une fois que la mémoire associée aux mappages suivants est utilisée. L’abandon peut être considéré comme une barrière entre une utilisation de la mémoire et une autre utilisation de la même mémoire. L’abandon facilite également l’outillage et la déduction de l’intention, car la mémoire n’est réutilisée qu’au niveau physique, et non au niveau virtuel. Les deux mappages différents ont des adresses virtuelles uniques. Si vous souhaitez créer intentionnellement un alias de mémoire (par exemple, superposer une cible de couleur à un tampon de stencil pour remplir rapidement le stencil), vous devez le faire en créant deux ressources placées à l’aide de la même adresse virtuelle du même mappage.Pseudocode de scénario
Considérez la séquence suivante de pseudo-appels d’API, en supposant qu’un moteur de disposition de mémoire a déjà été créé.- CreateLayout(“Rendertargets”, WorstCaseTotalPageCount, &layout)
- CreateMapping(“Shadow Map”, &mapping1)
- Map(mapping1, ShadowMapPageCount, ShadowMapEsramPageCount)
- CreatePlacedResourceX(mapping1.address, ShadowMapDesc, &pShadowMapResource)
- CreateMapping(“Color Target”, &mapping2)
- Map(mapping2, ColorTargetPageCount, ColorTargetEsramPageCount)
- CreatePlacedResourceX(mapping2.address, ColorTargetDesc, &pColorTargetResource)
- RelinquishMapping(mapping1)
- CreateMapping(“Post Effects Target”, &mapping3)
- Map(mapping3, PostEffectsPageCount, PostEffectsEsramPageCount)
- CreatePlacedResourceX(mapping3.address, PostEffectsDesc, &pPostEffectsResource)
- CreateLayout(“Rendertargets”, WorstCaseTotalPageCount, &layout)
- CreateMapping(“Shadow Map”, &mapping1)
- Map(mapping1, ShadowMapPageCount, ShadowMapEsramPageCount)
- CreatePlacedResourceX(mapping1.address, ShadowMapDesc, &pShadowMapResource)
- CreateMapping(“Color Target”, &mapping2)
- Map(mapping2, ColorTargetPageCount, ColorTargetEsramPageCount)
- CreatePlacedResourceX(mapping2.address, ColorTargetDesc, &pColorTargetResource)
- CreateMapping(“Depth Target”, &mapping4)
- Map(mapping4, DepthTargetPageCount, DepthTargetEsramPageCount)
- CreatePlacedResourceX(mapping4.address, DepthTargetDesc, &pDepthTargetResource)
- RelinquishMapping(mapping1)
- CreateMapping(“Post Effects Target”, &mapping3)
- Map(mapping3, PostEffectsPageCount, PostEffectsEsramPageCount)
- CreatePlacedResourceX(mapping3.address, PostEffectsDesc, &pPostEffectsResource)
