Strategien für die Arbeitsspeicherverwaltung
Ein Speicher-Manager für Direct3D 12 kann mit allen verschiedenen Unterstützungsebenen für UMA- oder diskrete (Nicht-UMA)-Adapter und mit einer beträchtlichen Bandbreite von Architekturunterschieden zwischen GPU-Adaptern schnell sehr kompliziert werden.
Die in diesem Abschnitt beschriebene empfohlene Strategie für die Direct3D 12-Speicherverwaltung ist "Klassifizieren, Budget und Stream".
Ressourcentypen
Das grundlegende Konzept einer "committeten Ressource" (Das Erstellen von virtuellen und physischen Adressräumen, die im verwalteten physischen Speicher initialisiert werden) gibt es seit Direct3D 9, obwohl die virtuelle Adressierung (VA) und die physische Adressierung in Direct3D 12 getrennt werden können, um der App die sorgfältige Verwaltung des physischen Arbeitsspeichers zu ermöglichen.
Zusätzlich zu committeten Ressourcen ermöglicht das Heapkonstrukt von Direct3D 12 zwei weitere Ressourcentypen: "platziert" und "reserviert". In Direct3D 11 wurde eine "reservierte" Ressource als "kachelierte Ressource" bezeichnet.
Reservierte Ressourcen unterscheiden sich von platzierten Ressourcen darin, dass reservierte Ressourcen über einen eigenen eindeutigen virtuellen GPU-Adressraum verfügen. Dies ermöglicht eine große Zuweisung von VA-Speicherplatz im Voraus und ermöglicht dann die Zuordnung von VA-Seiten zu bestimmten Abschnitten des Heaps später, und die Anwendung konfiguriert die Anordnung direkt neu. Der VA-Bereich ist zusammenhängend und kann nur spärlich zugeordnet werden.
Die reservierte Ressource kann durch API-Aufrufe wie UpdateTileMappings auf Regionen im Heap verwiesen werden, und sie können von der App als Resident festgelegt werden, indem Seitentabellen direkt aktualisiert werden. Wenn ein VA-Bereich NULL oder einem nicht residenten Heap zugeordnet wird, gilt dieser Teil der Ressource als nicht resident. Wenn ein VA-Bereich einem residenten Heap zugeordnet wird, gilt dieser Teil der Ressource als resident. Heaps sind bei der Erstellung ansässig.
Platzierte Ressourcen sind ein viel einfacheres Design und sind einfach ein Zeiger auf einen bestimmten Bereich eines Heaps (z. B. ein 1 MB-Bereich für eine Textur in einem 5-MB-Heap). Aliasingbarrieren ermöglichen die Verwendung von überlappenden platzierten Ressourcen (siehe CreatePlacedResource und ResourceBarrier).
Reservierte Ressourcen sind nicht auf der gesamten Direct3D 12-Hardware verfügbar, und platzierte Ressourcen sind ein vernünftiger Fallback, obwohl platzierte Ressourcen zusammenhängend sein müssen und nicht teilweise resident sein können.
Arbeitsspeicherbudget
Wenn Sie in Direct3D 12 einen Heap zuordnen, erstellen Sie den physischen Speicheraspekt einer committeten Ressource. Eine explizitere Speichersegmentauswahl ist in Direct3D 12 verfügbar (auswahl zwischen Video- und Systemspeicher). UMA-Adapter verfügen nur über ein einzelnes Speichersegment, den Systemspeicher.
GPUs unterstützen keine Seitenfehler, sodass Entwickler sich bewusst sein müssen, dass sie den Commit nicht übermäßig ausführen, insbesondere bei Systemen mit nur 1 GB Systemspeicher. Wenn eine App einen Over-Commit ausführt, verwendet das Betriebssystem eine grob abgestreckte Planung von Prozessen nach Bedarf an physischem Arbeitsspeicher. Der Planer friert Vordergrundprozesse ein und stellt im Wesentlichen einige davon aus, um einen Hintergrundprozess einzugeben, der ausgeführt werden soll. Der verfügbare physische Arbeitsspeicher kann je nachdem, was der Benutzer im Hintergrund tut (z. B. das Ausführen eines Browsers oder das Ansehen eines Videos) erheblich variieren.
Die API für das Speicherbudget lautet QueryVideoMemoryInfo. Bei diskreten Adaptern ist "lokal" Videospeicher, "nicht lokal" systeminterner Arbeitsspeicher. Bei UMA-Adaptern ist nicht lokal immer null. Eine Entwurfsfrage ist, ob Ihre Engine beide Budgets oder nur das lokale Budget verwaltet. Die Verwaltung des lokalen Budgets ist einfacher, hat aber einige Einschränkungen. Angenommen, es gibt ein maximales lokales Budget von 1 Gb, dann werden alle Heaps von diesen 1 Gb in einem UMA-System stammen, und es gibt keinen Überlauf auf den Systemspeicher (eindeutig, da es keinen gibt).
Da Direct3D11 verwalteter Arbeitsspeicher für Anwendungen verwaltet wird, würden ungenutzte Ressourcen im Wesentlichen ausgelagert.
Wählen Sie die am besten geeigneten Ressourcendimensionen aus. Überlegen Sie, ob die Größe einer Ressource für die Situation geeignet ist, in der die Anwendung tatsächlich ausgeführt wird. Einige Benutzer können die Anwendung in einem Fenster oder mit einer Bildschirmauflösung von 800 x 600 ausführen.
Klassifizierungsstrategie
Um Ressourcen in speichergebundenen Szenarien effektiv zu verwalten, sollten Sie ressourcen wie folgt klassifizieren:
Klassifizierung | Beispiele | Objekte und API-Features | Verwaltungsnotizen |
---|---|---|---|
Kritisch | Benutzeroberfläche des Spiels | Befehlszuweisung, Befehlswarteschlangen, Abfrageheaps, Ressourcen und Ressourcenheaps. | Diese Elemente sollten sich in nicht ausgelagerten/immer committeten Arbeitsspeicher befinden. |
Skaliert/Optional | Levelspezifische Modelle und Texturen, Swapchains, Sky boxes, First-Person-Spieler-Charaktermodelle | Ressourcen und Heaps. Commitsierte Ressourcen, aber auch platzierte und reservierte Ressourcen können genauso gut funktionieren. | Integrieren Sie das Budget für die Speicherresidenz in die Renderingalgorithmen. Wählen Sie die geeignete Ebene der verfügbaren Details aus, und werten Sie weniger als einmal pro Frame neu aus. Zu den Techniken gehören die Verwendung von Ressourcen variabler Größe und die Swapchainskalierung. |
Wiederverwendete Ressourcen | Schattenpuffer, verzögerte Renderingressourcen, Nachverarbeitungsressourcen, Beleuchtung von Datencaches | Ressourcen und Heaps. Überlappende platzierte Ressourcen auf Heaps und Aliasingbarrieren. | Verwenden Sie große Ressourcen oder Heapbereiche innerhalb eines Frames wieder, um die Anforderungen für den gesamten Frame zu reduzieren. Verwenden Sie die Technik der Wiederverwendung von Framespeicher. In Direct3D 11 konnten Anwendungen nur Ressourcen mit demselben Typ und potenziell ausreichend großen Dimensionen wiederverwenden. Direct3D 12-Heaps ermöglichen überlappende Ressourcen für eine viel einfachere und bessere Wiederverwendung. |
Streamingressourcen | Gelände, Open-World-Texturen und Geometrie | Ressourcen und Heaps. Freethreaderstellung, CPU-Hintergrundthreads und Befehlswarteschlangen und Listen zum Kopieren im Hintergrund. | Die partielle Residenz, die häufig auf Sichtbarkeit basiert (mithilfe der Ansichts frustum oder der entfernungsbasierten Auswertung), und die erneute Auswertung der Residenz benötigt jeden Frame. Die Technik der Verwendung einer partiellen Residency-Verwaltung pro Kachel und der frameübergreifenden Wiederverwendung ist verfügbar, wenn der GPU-Adapter reservierte Ressourcen innerhalb von Heaps unterstützt. Mit der Technik der Wiederverwendung von Speicher zwischen Framen kann eine teilweise Unterressourcenresidenz erreicht werden, ist aber weniger optimal. Platzierte Ressourcen mit Heaps sollten ein schnelleres Recycling ermöglichen, aber committete Ressourcen können als Fallback verwendet werden. |
Je mehr Anwendungen streamingressourcen für die meisten Aufgaben nutzen, desto mehr nutzen sie platzierte und reservierte Ressourcen, wodurch die Wiederverwendung des Arbeitsspeichers zwischen diesen vier Klassifizierungen maximiert wird. Je mehr Anwendungen streamen, desto mehr Budget und Priorisierung der Bandbreite.
In der Regel müssen Grafik-Engines mit Direct3D 12 ein vielfältigeres und dynamischeres Budget berücksichtigen und es strenger tun als in der Vergangenheit. Die besten Anwendungen finden alle vier Kategorien in dem Budget, das für den Prozess festgelegt wird, und skalieren das Spiel von der mobilen Hintergrund-App auf diskrete Budgets im Vollbildmodus. Aber viele Anwendungen werden wahrscheinlich Probleme haben, wenn sie mit zu vielen kritischen Ressourcentypen beginnen. Direct3D 11-fähige Ressourcen können anonym erstellt werden und wichtige status belegen, ohne die Leistung zu beeinträchtigen. Für Direct3D 12 müssen Entwickler jedoch in ihrer Engine und Middleware sorgfältig nach zufällig erstellten Ressourcen suchen und sie einer der anderen Kategorien erneut zuweisen.
Weitere Problembereiche sind Middlewarekomponenten, Benutzersteuerelemente und Frameinternes Streaming. Middlewarekomponenten sind möglicherweise nicht mit einem Budget verfügbar und müssen nicht eng zusammenarbeiten. Middlewarekomponenten könnten Features wahrscheinlich als Renderingtechniken verfügbar machen. und die Anwendung könnte sich auf das Verfügbarmachen von Middleware und Engine-Einstellungen verlassen. Entwickler konnten sich auf Direct3D 11 verlassen, um das Paging zu erledigen und die richtige Bildfrequenz zu erzielen. In einigen Fällen haben Direct3D 11-Anwendungen möglicherweise Ressourceninhalte in jeden Frame ein- und auslagern. und dies führte zu akzeptablen Bildfrequenzen für den Benutzer. Die meisten Engines streamen Ressourcendaten nur als Hintergrundaktivität, bei der es keinen ordnungsgemäßen Fallback auf das Frame-Streaming mit hoher Priorität gibt. Wenn Sie Engines bitten, dies zu implementieren, werden einige der CPU-Mehraufwandsgewinne untergraben, die sie durch die Umstellung auf Direct3D 12 erzielen möchten. Engine-Entwickler könnten erwägen, ihre Frames in Phasen einzuteilen, um mehr Möglichkeiten für wiederverwendbare Ressourcen zu bieten; und arbeiten wahrscheinlich mit Middlewareanbietern zusammen, um platzierte Ressourcen und Heaps für die Wiederverwendung des Framespeichers zu unterstützen.