Aufteilen eines DMA-Puffers
Geteilte Punkte werden vom Videospeicher-Manager verwendet, um ein großes Arbeitselement, das vom Anzeigeminiporttreiber übermittelt wird, in kleinere Arbeitselemente aufzuteilen, für die weniger GPU-Ressourcen zur Ausführung erforderlich sind. Beispielsweise kann ein großer DMA-Puffer auf eine Reihe von Zuordnungen verweisen, die möglicherweise nicht in den lokalen Videospeicher oder in den nicht lokalen Speicher passen können. Die einzige Möglichkeit, ein solches Arbeitselement zu verarbeiten, besteht darin, es in mehrere kleinere Arbeitselemente aufzuteilen, die weniger GPU-Ressourcen erfordern.
Hinweis DMA-Pufferteilung und DMA-Pufferlöschung sind verschiedene unabhängige Konzepte. Ein Display-Miniporttreiber muss immer das DMA-Puffersplitting unterstützen, auch auf einem System mit einer GPU, bei dem eine DMA-Pufferablösung nicht möglich ist. Auf einem System mit einer GPU, bei dem das Speichern und Wiederherstellen im Kontext nicht möglich ist, plant der GPU-Planer Teile eines DMA-Puffers zurück, um sicherzustellen, dass die geteilten Teile nicht mit einem anderen DMA-Puffer aus einem anderen GPU-Kontext verschachtelt werden. Ein Pagingpuffer sollte jedoch zwischen Teilen eines geteilten DMA-Puffers übermittelt werden, da Pagingvorgänge zwischen geteilten Teilen eines DMA-Puffers erforderlich sind. Jeder Splitpunkt, den der Treiber zum Erstellen eines DMA-Datenstroms der Anwendung verwendet, wird vom Videospeicher-Manager verwendet. Ein übermittelter DMA-Puffer sollte nach jedem Splitpunkt genügend GPU-Zustand umprogrammieren, um einen potenziellen Auslagerungspuffer zu berücksichtigen, der möglicherweise an dieser Stelle eingefügt wird.
Um Splitpunkte anzugeben, gibt der Anzeigeminiporttreiber Werte im SplitOffset - und SlotId-Element der D3DDDI_PATCHLOCATIONLIST-Struktur für jede Zuordnung an, auf die im AllocationIndex-Member von D3DDDI_PATCHLOCATIONLIST verwiesen wird. Um die Zuordnungsverwendung in einem bestimmten DMA-Puffer nachzuverfolgen, erstellt der Videospeicher-Manager die erforderlichen Dimensionen eines Arrays mithilfe des MaxAllocationListSlotId-Members der DXGK_DRIVERCAPS-Struktur , die der Treiber über einen Aufruf seiner DxgkDdiQueryAdapterInfo-Funktion bereitgestellt hat. Dieses Array wird bei null initialisiert und als Teileinträge der Patchspeicherortliste verarbeitet. Das SlotId-Element von D3DDDI_PATCHLOCATIONLIST für den Patchspeicherort gibt an, welche Zeile der Ressourcentabelle aktualisiert werden muss, während der SplitOffset-Member den Offset innerhalb des DMA-Puffers angibt, in dem die Zuordnung erforderlich ist. Der DMA-Puffer kann bis zu dem von SplitOffset angegebenen Punkt ausgeführt werden, ohne dass die GPU auf die Ressource zugreifen kann. Wenn ein neuer Teileintrag für patch-location split auf dieselbe SlotId verweist, wird die vorherige Zuordnung durch die neue Zuordnung ersetzt, und die vorherige Zuordnung ist nicht mehr erforderlich (das heißt, die vorherige Zuordnung kann ausgelagert werden).
Beim Paging der ressourcen, die für einen DMA-Puffer benötigt werden, verarbeitet der Videospeicher-Manager die Patchspeicherliste, indem er mit dem ersten Element beginnt und zum letzten Element nach unten wechselt. Die D3DDDI_PATCHLOCATIONLIST Elemente, die vom Treiber ausgefüllt werden, müssen Werte in ihren SplitOffset-Membern enthalten. die Elemente werden streng erhöht (d. h. Zuordnungen müssen in der Reihenfolge angezeigt werden, in der sie im Stream verwendet werden). Die Videospeicher-Manager-Seiten in Zuordnungen, auf die in der Patchspeicherortliste in der angegebenen Reihenfolge verwiesen wird. Wenn ein Punkt erreicht ist, an dem der Videospeicher-Manager eine Zuordnung aufgrund einer niedrigen Speicherbedingung nicht mehr einblättern kann, übermittelt der Videospeicher-Manager den aktuellen Teil des DMA-Puffers, der zur Ausführung vorbereitet wird, an den GPU-Planer. Der DMA-Puffer wird vom Anfang des vorherigen Splitpunkts bis zum SplitOffset-Wert ausgeführt, der für eine Zuordnung angegeben wird, die nicht abgerufen werden konnte. Nach der Übermittlung bestimmt der Videospeicher-Manager die Liste der erforderlichen Zuordnungen am aktuellen geteilten Offset im DMA-Stream mithilfe der Ressourcentabelle. Alle Zuordnungen in der Tabelle werden an ihrem aktuellen physischen Speicherort beibehalten, während andere Zuordnungen, die nicht mehr verwendet werden, möglicherweise entfernt werden. Der Videospeicher-Manager verarbeitet die Patchspeicherliste dann weiter und teilt sich möglicherweise mehrmals erneut.
Der Treiber sollte bei jeder Bindung oder ungebundenen Zuordnung Splitpunkte angeben. Um anzugeben, dass eine Zuordnung ungebunden ist, kann der Treiber im hDeviceSpecificAllocation-Member der DXGK_ALLOCATIONLIST-Struktur ein NULL-Zuordnungshandle mit dem entsprechenden Wert im SlotId-Member des zugeordneten D3DDDI_PATCHLOCATIONLIST angeben. Der Treiber sollte die Bindung großer Ressourcen aufheben, um die Wahrscheinlichkeit zu erhöhen, dass der Videospeicher-Manager komplexe Speicherplatzierungsprobleme lösen kann.
Ebenso sollte der Treiber große Ressourcen an jedem Teilpunkt neuprogrammieren. Beim Verwenden eines Splitpunkts ist der Videospeicher-Manager gezwungen, eine zuvor gebundene Zuordnung an die vorherige Zuordnung zu belassen. Dies führt zu einer Fragmentierung des Arbeitsspeichers, die zu einem Fehler bei der Lösung komplexer Speicherplatzierungsprobleme führen kann, die ohne die zuvor begrenzte Zuordnungsbeschränkung möglicherweise gelöst wurden. Beim Berechnen des Zustands an einem Geteilten Punkt bestimmt der Videospeicher-Manager, welcher Slotbezeichner (SlotId) an diesem Splitpunkt neu programmiert wird (d. h. jedes Patch-Location-Listenelement, das denselben SplitOffset-Wert wie andere Elemente verwendet) und ignoriert die Platzierungsbeschränkung für diesen Splitpunkt. Wenn der Treiber beispielsweise eine 64-MB-Textur verwendet, erhält der Videospeicher-Manager die Flexibilität, diese Textur bei Bedarf zwischen Splitpunkten zu verschieben.