Fractionnement d’une mémoire tampon DMA

Les points de fractionnement sont utilisés par le gestionnaire de mémoire vidéo pour diviser un élément de travail volumineux soumis par le pilote miniport d’affichage en éléments de travail plus petits qui nécessitent moins de ressources GPU pour s’exécuter. Par exemple, une mémoire tampon DMA volumineuse peut référencer un ensemble d’allocations qui ne peuvent peut-être pas tenir dans la mémoire vidéo locale ou la mémoire non locale. La seule façon de traiter un tel élément de travail consiste à le diviser en plusieurs éléments de travail plus petits qui nécessitent moins de ressources GPU.

Note Le fractionnement de la mémoire tampon DMA et la préemption de la mémoire tampon DMA sont des concepts indépendants différents. Un pilote de miniport d’affichage doit toujours prendre en charge le fractionnement de mémoire tampon DMA, même sur un système doté d’un GPU où la préemption de la mémoire tampon DMA n’est pas possible. Sur un système avec un GPU où l’enregistrement et la restauration de contexte ne sont pas possibles, le planificateur GPU planifie le fractionnement des parties d’une mémoire tampon DMA dos à dos, en veillant à ce que les parties fractionnées ne soient pas entrelacées avec une autre mémoire tampon DMA à partir d’un autre contexte GPU. Toutefois, une mémoire tampon de pagination doit être envoyée entre des parties d’une mémoire tampon DMA fractionnée, car les opérations de pagination sont requises entre les parties fractionnées d’une mémoire tampon DMA. Chaque point de fractionnement utilisé par le pilote pour générer un flux DMA d’application est utilisé par le gestionnaire de mémoire vidéo. Une mémoire tampon DMA soumise doit reprogrammer suffisamment d’état GPU après chaque point de fractionnement pour tenir compte d’une mémoire tampon de pagination potentielle qui peut être insérée à cet emplacement.

Pour spécifier des points de fractionnement, le pilote miniport d’affichage spécifie des valeurs dans les membres SplitOffset et SlotId de la structure D3DDDI_PATCHLOCATIONLIST pour chaque allocation référencée dans le membre AllocationIndex de D3DDDI_PATCHLOCATIONLIST. Pour suivre l’utilisation de l’allocation dans une mémoire tampon DMA particulière, le gestionnaire de mémoire vidéo crée les dimensions requises d’un tableau à l’aide du membre MaxAllocationListSlotId de la structure DXGK_DRIVERCAPS que le pilote a fourni via un appel à sa fonction DxgkDdiQueryAdapterInfo . Ce tableau est initialisé à zéro et est rempli au fur et à mesure que les entrées fractionnées de la liste de l’emplacement des correctifs sont traitées. Le membre SlotId de D3DDDI_PATCHLOCATIONLIST pour l’emplacement du correctif indique la ligne de la table de ressources à mettre à jour, tandis que le membre SplitOffset indique le décalage dans la mémoire tampon DMA où l’allocation est requise. La mémoire tampon DMA peut être exécutée jusqu’au point spécifié par SplitOffset sans que la ressource soit accessible au GPU. De même, si une nouvelle entrée de partie fractionnée d’emplacement de correctif fait référence au même SlotId, l’allocation précédente est remplacée par la nouvelle allocation et l’allocation précédente n’est plus nécessaire (autrement dit, l’allocation précédente peut être paginée).

Lors de la pagination dans les ressources requises par une mémoire tampon DMA, le gestionnaire de mémoire vidéo traite la liste d’emplacements correctifs en commençant par le premier élément et en descendant vers le dernier élément. Les éléments D3DDDI_PATCHLOCATIONLIST qui sont remplis par le pilote doivent contenir des valeurs dans leurs membres SplitOffset ; les éléments sont strictement croissants (autrement dit, les allocations doivent apparaître dans l’ordre dans lequel elles sont utilisées dans le flux). Le gestionnaire de mémoire vidéo pages dans les allocations qui sont référencées dans la liste des emplacements de correctif dans l’ordre dans lequel elles sont fournies. Lorsqu’un point est atteint où le gestionnaire de mémoire vidéo ne peut plus pager une allocation en raison d’une insuffisance de mémoire, le gestionnaire de mémoire vidéo envoie la partie actuelle de la mémoire tampon DMA en cours de préparation au planificateur GPU pour l’exécution. La mémoire tampon DMA est exécutée à partir du début du point de fractionnement précédent jusqu’à la valeur SplitOffset spécifiée pour une allocation qui n’a pas pu être apportée. Une fois envoyé, le gestionnaire de mémoire vidéo détermine la liste des allocations requises au décalage de fractionnement actuel dans le flux DMA à l’aide de la table de ressources. Toutes les allocations sur la table sont conservées à leur emplacement physique actuel, tandis que d’autres allocations qui ne sont plus utilisées peuvent être supprimées. Le gestionnaire de mémoire vidéo continue ensuite de traiter la liste de l’emplacement des correctifs, potentiellement fractionné plusieurs fois.

Le pilote doit spécifier des points de fractionnement chaque fois qu’une allocation est liée ou non liée. Pour spécifier qu’une allocation n’est pas liée, le pilote peut spécifier un handle d’allocation NULL dans le membre hDeviceSpecificAllocation de la structure DXGK_ALLOCATIONLIST avec la valeur appropriée dans le membre SlotId du D3DDDI_PATCHLOCATIONLIST associé. Le pilote doit dissocier des ressources volumineuses pour augmenter les chances que le gestionnaire de mémoire vidéo puisse résoudre des problèmes complexes de placement de la mémoire.

De même, le pilote doit reprogrammer des ressources volumineuses à chaque point de fractionnement. Lors de la prise d’un point de fractionnement, le gestionnaire de mémoire vidéo est forcé de laisser une allocation précédemment liée à l’allocation précédente. Cela entraîne une fragmentation de la mémoire qui peut entraîner un échec de la résolution des problèmes complexes de placement de la mémoire qui auraient pu être résolus si ce n’était pas pour la restriction d’allocation précédemment liée. Lors du calcul de l’état à un point de fractionnement, le gestionnaire de mémoire vidéo détermine l’identificateur d’emplacement (SlotId) qui est reprogrammé à ce point de fractionnement (autrement dit, chaque élément de liste d’emplacement de correctif qui partage la même valeur SplitOffset avec d’autres éléments) et ignore la restriction de placement sur ce point de fractionnement. Par exemple, si le pilote utilise une texture de 64 Mo, la reprogrammation de cette texture à chaque point de fractionnement donne au gestionnaire de mémoire vidéo la possibilité de déplacer cette texture en mémoire entre des points de fractionnement si nécessaire.