Unity durchsuchen

Eine Szene, 10 Grafik-Optimierungen für Konsolen-Entwickler

Last updated: January 2019

What you will get from this page: Console graphics optimization tips, courtesy of Unity’s Rob Thompson, a console graphics developer (who auf der Unite präsentierte), and our demo team. These optimizations were made to an especially difficult scene to ensure smooth 30fps performance.

AAA-Qualität mit Unitys Scriptable-Render-Pipelines

"Book of the Dead" (in this article we refer to it as BOTD) was produced by Unity's demo team. It’s a real-time rendered animated short, essentially created to test-drive and show off the capabilities of the new (and still experimental) Scriptable Render Pipelines (SRP). The SRPs allow you to code the core of your render loop in C#, thereby giving you much more flexibility for customizing how your scene is drawn to make it specific to your content.

console scriptable rendering pipeline

There are two SRPs available: the High-Definition-Render-Pipeline (HDRP) which offers all of the features that you'd expect from a modern, AAA quality, high fidelity renderer, while the Lightweight-Render-Pipeline (LWRP) maintains responsive performance when scaling for mobile. BOTD uses the HDRP, and you can find advanced learning resources for the SRPs at the end of this article.

All of the assets and all of the script code for BOTD are für Sie verfügbar in the Asset Store.

Eine wichtige Optimierung, um auf Konsolen 1080 p bei 30 fps (oder besser) zu erreichen

Das Ziel der Präsentation war, eine interaktive Erfahrung zu zeigen, in der man sich bewegen und die man erfassen konnte. Sie sollte ein Erlebnis bieten, das einem aus der Perspektive traditioneller AAA-Spiele bekannt war. Insbesondere wollten wir BOTD auf Xbox One und PS4 zeigen. Unsere Performance-Anforderungen lagen bei 1080 p bei 30 fps oder besser.

Da es sich um eine Präsentation und nicht um ein vollständiges Spiel handelt, lag das Hauptaugenmerk bei den Optimierungen auf dem Rendering.

Allgemein ist die Performance für BOTD recht gleichmäßig, da keine Szenen enthalten sind, in denen beispielsweise plötzlich Tausende Partikel spawnen oder zahlreiche animierte Charaktere erscheinen.

Als Ausgangspunkt suchten Rob und das Demo-Team die Ansicht heraus, deren Performance hinsichtlich der GPU-Auslastung am schlechtesten war. Hier ein Screenshot davon:

console scriptable rendering pipeline

Was in der Szene passiert, ist ziemlich konstant; unterschiedlich ist nur, was sich im Blick der Kamera befindet. Durch Einsparungen in dieser Szene könnte eine verbesserte Performance für die gesamte Präsentation erreicht werden.

Der Grund für die schlechte Performance dieser Szene ist, dass es sich dabei um die Außenansicht des Levels handelt und man ins Zentrum blickt, sodass die Mehrzahl der Assets sich im Kamera-Sichtvolumen (Frustum) befinden. Dies hat zahlreiche Drawcalls zur Folge.

Zusammengefasst wurde diese Szene folgendermaßen gerendert:

  • Mit der HDRP
  • Die meisten der von Grafikern verfassten Texturen sind Maps zwischen 1 K und 2 K Größe, einige 4 K.
  • Für indirekte Beleuchtung wurde Baked Occlusion und Baked GI eingesetzt, sowie eine einzelne dynamische, schattenwerfende Lichtquelle für direkte Beleuchtung durch die Sonne.
  • An jedem Punkt werden mehrere tausend Drawcalls erstellt (Drawcalls und Compute-Shader-Dispatches).
  • Zu Beginn des Optimierungspasses war die Ansicht auf PS4 Pro bei etwa 45 Millisekunden GPU-gebunden.
Was der GPU-Frame vor dem Optimierungspass zeigte

Zu Beginn des Optimierungspasses sahen Rob und sein Team sich den GPU-Frame Schritt für Schritt an und stellten die folgende Performance fest:

  • The Gbuffer was at 11ms (you can find a description of the Gbuffer layouts for HDRP in diesem Beitrag by Unity lead graphics developer Sebastien Lagarde)
  • Motion Vectors und Screen Space Ambient Occlusion waren ziemlich schnell, bei .25 beziehungsweise .6 ms
  • Shadow-Maps des Directional Shadow Casting mit dynamischer Beleuchtung lagen bei sage und schreibe 13,9 ms
  • Deferred Lighting lag bei 4,9 ms
  • Atmospheric Scattering lag bei 6,6 ms

So sah der GPU-Frame aus, von Anfang bis Ende:

console GPU frame

Wie Sie sehen, stand das Team bei 45 Millisekunden. Die beiden orangefarbenen senkrechten Linien zeigen, wo es stehen musste, um 30 fps bzw. 60 fps zu erreichen.

10 Wege, wie das Rendering für "Book of the Dead" optimiert wurde

Kontrolle der Batch-Anzahl

Die CPU-Performance war kein großes Problem für das Team, weil BOTD eine Präsentation und kein Spiel ist, was bedeutet, dass die Verwicklungen, die mit dem Script-Code für alle Systeme einhergehen, die bei vollständigen Spielen benötigt werden, nicht entstehen konnten. Wieder lag das Hauptaugenmerk auf der Optimierung des Rendering.

However keeping the batch count low is still a valuable tip for any platform. The team did this by using Occlusion Culling, and, primarily, GPU-Instancing. Avoid using Dynamic batching on consoles unless you are sure it’s providing a performance win.

In diesem Fall war GPU-Instancing die nützlichste Methode. Ohne hätte es 4500 Batches für diese Szene gegeben. Mit GPU-Instancing konnte die Anzahl auf 1832 reduziert werden.

Ein weiterer Kernpunkt: Zur Erstellung dieser Szene wurde tatsächlich nur eine sehr geringe Anzahl individueller Assets verwendet. Dank der hohen Qualität dieser Assets und ihrer intelligenten Platzierung konnte das Team komplexe Szenen erstellen, die nicht monoton wirken, und die Batch-Anzahl mit GPU-Instancing gering halten.

Dies ist die Szene ohne Instancing.

console scriptable rendering pipeline

Und hier mit Instancing:

console scriptable rendering pipeline

Nutzen Sie die Kerne, die auf Konsolen verfügbar sind

Sowohl Xbox One als auch PS4 sind Multicore-Geräte. Um die beste CPU-Performance zu erreichen, müssen wir versuchen, diese Kerne auch die ganze Zeit zu beschäftigen.

If you follow Unity news, you’ll know that Unity is currently developing ein leistungsfähiges Multithread-System, that will make it possible for your game to fully utilise the multicore processors available today and in the future. (Very) briefly, this system comprises three sub-systems: the Entity-Component-System, the C#-Jobsystem and the Burst-Compiler.

Das neue Multithread-System ist noch im frühen experimentellen Modus. In Unitys Grafiksystem können Sie es über den "Graphics Jobs"-Modus ausprobieren (ebenfalls im experimentellen Modus). Sie finden die Graphics-Jobs-Bedienelemente unter Player Settings -> Other Settings.

console Graphics Jobs

Der Graphics-Jobs-Modus bietet Ihnen unter fast allen Umständen eine Performance-Optimierung auf Konsolen, es sei denn, Sie verwenden tatsächlich nur eine Handvoll Batches. Es sind zwei Arten verfügbar:

  • Legacy Jobs, verfügbar auf PS4, und DirectX 11 für Xbox One
    • Entlastet den Haupt-Thread, indem Arbeit auf andere Kerne verteilt wird. Bedenken Sie, dass dies bei sehr großen Szenen ein Engpass im "Render Thread" sein kann, einem Thread, den Unity verwendet, um die Grafik-API des Plattforminhabers anzusprechen.
  • Native Jobs, verfügbar auf PS4, und DirectX 12 für Xbox One (in Kürze)
    • Verteilt einen Großteil der Arbeit auf verfügbare Kerne und ist die beste Option für große Szenen.
    • Sollte ab Version 2018.2 immer die beste Option sein (in Version 2018.1 oder früher kann eine höhere Arbeitslast für den Main-Thread anfallen, was zum Nachlassen der Performance führen kann).

Nutzen Sie die Performance-Analysetools des Plattforminhabers

Microsoft and Sony provide hervorragende Tools for analyzing your project’s performance both on the CPU and on the GPU. These tools are available to you for free if you're working on console. Learn them early on and keep using them throughout your development cycle. Pix for Xbox One is Microsoft's offering and the Razor Suite is Sony's; as Rob says, they are your main tools in your arsenal when it comes to optimization on these platforms.

Achten Sie auf Ihre Post-Processing-Effekte

Rob erzählt, dass er Unity-Spiele auf PS4 analysiert hat, bei denen ⅔ der Framerate auf das Konto von Post-Processing-Effekten gingen – ohne dass dies den Entwicklern bewusst war. Oft wird dies durch das Herunterladen von Assets aus dem Asset Store verursacht, die eigentlich für den PC gedacht sind. Die Assets scheinen auf der Konsole gut zu laufen, zeigen aber tatsächlich schlechte Performance-Eigenschaften.

So, when solche Effekte anwenden, profile how long they take on the GPU, and iterate until you find a happy balance between visual quality and performance. And then, leave them alone, because they comprise a static cost in every scene, meaning you know how much GPU bandwidth is left over to work with.

Vermeiden Sie Tesselation (es sei denn, Sie haben einen sehr guten Grund dafür)

Allgemein ist es nicht ratsam, Tesselation für die Grafik eines Konsolenspiels einzusetzen. In den meisten Fällen ist es besser, die entsprechenden Grafik-Assets zu nutzen, statt eine Laufzeit-Tesselation auf der GPU durchzuführen.

Aber im Fall von BOTD gab es einen guten Grund, Tesselation einzusetzen: für das Rendering der Baumrinde.

console tesselation

Tesseliertes Displacement ermöglichte dem Team, der Geometrie die Vertiefungen und knorrigen Details hinzuzufügen, die selbst die richtigen Schatten werfen, was mit normalem Mapping nicht möglich gewesen wäre.

Da die Bäume über weite Strecken "Hero"-Objekte in BOTD sind, war dieses Vorgehen gerechtfertigt. Verwirklicht wurde es durch ein gleiches Mesh für die Bäume auf LOD 0 und LOD 1. Der Unterschied zwischen den beiden ist lediglich, dass das tesselierte Displacement rückskaliert wurde, sodass es nicht länger in Kraft war, wenn LOD 1 erreicht wurde.

Achten Sie immer auf eine vernünftige Wavefront-Occupancy auf der GPU

Okay, das ist leicht gesagt, aber Wavefront-Occupancy ist tatsächlich ein wichtiger Faktor.

Eine Wavefront kann man sich als ein Paket mit GPU-Arbeit vorstellen. Wird ein Drawcall oder ein Compute Shader Dispatch an die GPU gesendet, wird dieses Arbeitspaket in viele einzelne Wavefronts aufgeteilt, die überall auf den SIMDs in allen Recheneinheiten, die auf der GPU verfügbar sind, verteilt werden.

console wave front occupancy

Jeder SIMD kann zu einem bestimmten Zeitpunkt eine bestimmte maximale Anzahl von Wavefronts verarbeiten, es gibt also eine maximale Gesamtzahl an Wavefronts, die zu einem bestimmten Zeitpunkt parallel auf der GPU vorhanden sein können. Die Anzahl der verwendeten Wavefronts wird durch die Wavefront-Occupancy angegeben. Dies ist ein sehr nützlicher Wert um zu erfassen, wie gut das Potenzial der GPU für parallel ablaufende Vorgänge ausgenutzt wird.

Pix und Razor zeigen die Wavefront-Occupancy sehr detailliert an. Die Graphen oben sind von Pix für Xbox One. Links sehen wir ein Beispiel für gute Wavefront-Occupancy. Unten, entlang des grünen Streifens, erkennen wir einige Vertex-Shader-Wavefronts und darüber, in blau, Pixel-Shader-Wavefronts.

Rechts können wir jedoch ein Performance-Problem erkennen: Die Vertex-Shader-Arbeit führt hier kaum zu Pixel-Shader-Aktivität. Das Potenzial der GPU wird nicht hinreichend genutzt, und das führt uns zu unserem nächsten Optimierungstipp.

Wie kommt es dazu? Dieses Szenario ist typisch, wenn Shader-Arbeit verrichtet wird, die nicht in Pixel resultiert.

Verwenden Sie Depth Prepass

Weitere Analysen mit Pix und Razor ergaben, dass es während des Gbuffer-Passes zu viel Overdraw kam. Dies wirkt sich auf Konsolen besonders negativ aus, was alpha-getestete Objekte angeht.

Auf Konsolen kann man den Vorteil der frühen Depth-Rejection nicht mehr nutzen, wenn man Pixel-Discard-Anweisungen ausgibt oder direkt in die Pixel-Shader-Depth schreibt. Die Pixel-Shader-Wavefronts werden in jedem Fall ausgeführt, auch wenn die Arbeit letztendlich verworfen wird.

Die Lösung war hier das Hinzufügen eines Depth-Prepass. Ein Depth-Prepass beinhaltet das ausschließliche Rendern der Szene zur Depth im Voraus, wobei alle Light-Shader verwendet werden, die dann die Basis einer intelligenteren Depth-Rejection bilden können, wo Ihre Gbuffer-Shader eingebunden sind.

The HDRP now includes a Depth Prepass for all alpha tested objects, but you can also switch on a full Depth Prepass if you want. The settings for controlling HDRP, what render passes are used, and features enabled, are all made available via the .

Wenn Sie in einem HDRP-Projekt nach dem HD-Render-Pipeline-Asset suchen, werden Sie zahlreiche Kontrollkästchen finden, mit denen Sie alles festlegen können, was die HDRP tut.

Für BOTD war die Verwendung von Depth-Prepass ein großer GPU-Gewinn, aber Sie sollten bedenken, dass dadurch noch mehr Batches hinzugefügt werden, die auf die CPU zurückgreifen.

Reduzieren Sie die Größe Ihrer Shadow-Mapping-Render-Targets

Wie bereits erwähnt, werden die Shadow-Maps in dieser Szene gegen ein einzelnes schattenwerfendes Directional Light erzeugt. Vier Shadow-Map-Splits wurden verwendet, die zunächst zu einer 4K-Shadow-Map mit 32-bit-Tiefe renderten, was der Standard für HDRP-Projekte ist. Beim Rendern zu Shadow-Maps ist die Auflösung der Shadow-Map fast immer der limitierende Faktor; dies bestätigte sich durch die Analyse in Pix und Razor.

Die offensichtliche Lösung war eine Verringerung der Shadow-Map-Auflösung, obwohl sich dies auf die Qualität auswirken konnte.

The shadow map resolution was dropped to 3k, which provided a perfectly acceptable trade-off against performance. The demo team also added an option specifically to allow developers to render to 16-bit depth Shadow maps. If you want to give that a go for yourself herunterladen the project assets.

Schließlich musste das Team wegen der Änderung der Shadow-Map-Auflösung noch einige Beleuchtungseinstellungen ändern.

Reduce size of shadow

An diesem Punkt hatte das Team die Shadow-Maps bereits überarbeitet und die Shadow-Mapping-Kamera neu positioniert, um die beste Verwertung der neuen, reduzierten Auflösung zu erreichen. Was taten sie als Nächstes?

Rufen Sie beim Level-Load nur den letzten (am stärksten herausgezoomten) Shadow-Map-Split auf

Da sich die Shadow-Mapping-Kamera nicht viel bewegt, hat dies für das Team funktioniert. Der am stärksten herausgezoomte Split wird normalerweise für das Rendern der Schatten verwendet, die am weitesten von der Spielerkamera entfernt sind.

Das Team konnte keinen Qualitätsverlust feststellen. Die Optimierung stellte sich als ausgesprochen klug heraus, da sie sowohl GPU-Framerate-Zeit einsparte als auch die Batch-Anzahl auf der CPU reduzierte.

Nach all diesen Optimierungen lag die Erstellungsphase der Shadow-Map bei unter 8 ms statt bei 13 ms; der Lighting-Pass sank von 4,9 ms auf 4,4 ms, der Atmospherics-Pass von 6,6 ms auf 4,2 ms.

An diesem Punkt konnte das Team die Shadow-Mapping-Optimierung beenden. Sie liegen jetzt in dem Bereich, in dem sie 30 fps auf der PS4 Pro erreichen können.

console GPU frame

Verwenden Sie Async Compute

Async Compute is a method available for minimizing periods of underutilization on the GPU with useful Compute-Shader- work. It’s currently only supported on PS4, but coming to DX12 for Xbox One very soon. It's accessible through Unity's Command Buffer interface. It's not just exclusively for the SRP but is primarily aimed at it. Code examples are available in the BOTD assets, or look at the HDR PSOS.

Die Depth-Only-Phase, die mit Shadow-Mapping durchgeführt wird, ist traditionell der Zeitpunkt, an dem das Potenzial der GPU nicht voll ausgenutzt wird. Async Compute ermöglicht Ihnen, die Compute-Shader-Arbeit parallel zur Grafik-Queue ablaufen zu lassen und so die Ressourcen zu nutzen, die die Grafik-Queue brachliegen lässt.

BOTD verwendet Async Compute für die Tiled-Light-Listensammlung, die zum Deferred Lighting gehört, wobei alles hauptsächlich mit Compute-Shadern in HDRP auf der Konsole erledigt wird. Außerdem setzt BOTD es für die SSAO-Berechnungen ein. Beides überschneidet sich mit dem Shadow-Map-Rendering, um die Lücken bei der Wavefront-Ausnutzung zu schließen.

For a run-through of some conceptual code where Async Compute is employed, tune into Robs Unite-Session at 35:30.

Weitere Ressourcen

Wir wollen es wissen! Haben Ihnen diese Inhalte gefallen?

Ja, weiter so. Na ja. Könnte besser sein.
Alles klar

Wir verwenden Cookies, damit wir Ihnen die beste Nutzererfahrung auf unserer Website bieten können. Weitere Informationen erhalten Sie in unserer Cookie-Richtlinie.