Leistung – MRTK2

Erste Schritte

Die einfachste Möglichkeit, die Leistung zu rationalisieren, ist die Framerate oder das Rendern eines Bilds pro Sekunde durch Ihre Anwendung. Es ist wichtig, die Zielframerate zu erfüllen, wie durch die Zielplattform (z. B. Windows Mixed Reality, Oculus usw.) beschrieben wird. Bei HoloLens beträgt die Zielframerate beispielsweise 60 FPS. Anwendungen mit niedriger Framerate können zu schlechteren Benutzererfahrungen führen, z. B. zu einer verschlechterten Hologrammstabilisierung, Weltverfolgung, Handtracking und mehr. Um Entwicklern das Nachverfolgen und Erreichen einer qualitativ hochwertigen Framerate zu erleichtern, bietet Mixed Reality Toolkit eine Vielzahl von Tools und Skripts.

Visueller Profiler

Um die Leistung während der Lebensdauer der Entwicklung kontinuierlich nachzuverfolgen, wird dringend empfohlen, beim Ausführen & Debuggen einer Anwendung immer ein Visuelles mit Framerate anzuzeigen. Mixed Reality Toolkit stellt das Visual Profiler-Diagnosetool bereit, das Echtzeitinformationen zur aktuellen FPS- und Speicherauslastung in der Anwendungsansicht bereitstellt. Der visuelle Profiler kann über die Diagnosesystemeinstellungen unter dem MRTK-Profilinspektor konfiguriert werden.

Darüber hinaus ist es besonders wichtig, den Visual Profiler zu verwenden, um die Framerate zu verfolgen, wenn auf dem Gerät ausgeführt wird, anstatt im Unity-Editor oder einem Emulator auszuführen. Die genauesten Leistungsergebnisse werden bei der Ausführung auf dem Gerät mit Releasekonfigurationsbuilds angezeigt.

Hinweis

Wenn Sie für Windows Mixed Reality erstellen, stellen Sie mit MASTER-Konfigurationsbuilds bereit.

Visual Profiler-Schnittstelle

Optimierungsfenster

Das MRTK-Optimierungsfenster bietet Informationen und Automatisierungstools, mit denen Mixed Reality-Entwickler ihre Umgebung für die besten Ergebnisse einrichten und potenzielle Engpässe in ihrer Szene & Ressourcen identifizieren können. Bestimmte Wichtige Konfigurationen in Unity können wesentlich optimierte Ergebnisse für Mixed Reality-Projekte liefern.

Im Allgemeinen umfassen diese Einstellungen Renderingkonfigurationen, die ideal für Mixed Reality sind. Mixed Reality-Anwendungen sind im Vergleich zur herkömmlichen 3D-Grafikentwicklung einzigartig, da zwei Bildschirme (d. h. zwei Augen) für die gesamte Szene gerendert werden können.

Die empfohlenen Einstellungen, auf die unten verwiesen wird, können in einem Unity-Projekt automatisch konfiguriert werden, indem das MRTK-Optimierungsfenster verwendet wird.

MRTK-Optimierungsfenstereinstellungen

Unity Profiler

Unity Profiler ist ein nützliches Tool, um Details zur Anwendungsleistung auf Frame-für-Frame-Ebene zu untersuchen.

Für die CPU aufgewendete Zeit

Beispiel für Unity Profiler Graph

Um komfortable Bildfrequenzen (in der Regel 60 Frames pro Sekunde) aufrechtzuerhalten, müssen Anwendungen eine maximale Framezeit von 16,6 Millisekunden CPU-Zeit erreichen. Um die Kosten der MRTK-Funktionalität zu ermitteln, enthält Das Microsoft Mixed Reality Toolkit eine Markierung für Codepfade für innere Schleifen (pro Frame). Diese Marker verwenden das folgende Format, um die spezifischen Funktionen zu verstehen, die verwendet werden:

[MRTK] className.methodName

Hinweis

Es können zusätzliche Daten nach dem Methodennamen vorhanden sein. Dies wird verwendet, um bedingt ausgeführte, potenziell teure Funktionen zu identifizieren, die durch kleine Änderungen am Anwendungscode vermieden werden können.

Beispielhierarchie für Unity Profiler

In diesem Beispiel wurde die Hierarchie erweitert, um anzuzeigen, dass die UpdateHandData-Methode der WindowsMixedRealityArticulatedHand-Klasse während des analysierten Frames 0,44 ms CPU-Zeit verbraucht. Diese Daten können verwendet werden, um festzustellen, ob ein Leistungsproblem im Zusammenhang mit Anwendungscode oder von einer anderen Stelle im System steht.

Entwicklern wird dringend empfohlen, Anwendungscode auf ähnliche Weise zu instrumentieren. Die Hauptschwerpunkte für die Instrumentierung von Anwendungscode liegen innerhalb von Ereignishandlern, da diese Methoden der MRTK-Updateschleife in Rechnung gestellt werden, wenn Ereignisse ausgelöst werden. Hohe Framezeiten innerhalb der MRTK-Updateschleife können auf kostspieligen Code in Ereignishandlermethoden hindeuten.

Single-Pass Instanzrendering

Die Standard-Renderingkonfiguration für XR in Unity ist Multidurchlauf. Diese Einstellung weist Unity an, die gesamte Renderpipeline zweimal auszuführen, einmal für jedes Auge. Dies kann optimiert werden, indem Sie stattdessen Single Pass Instanced rendering (Single Pass Instanced) auswählen. Diese Konfiguration nutzt Renderzielarrays , um einen einzelnen Draw-Aufruf ausführen zu können, der Instanzen in das entsprechende Renderziel für jedes Auge eingibt. Darüber hinaus ermöglicht dieser Modus das gesamte Rendering in einer einzigen Ausführung der Renderingpipeline. Daher kann die Auswahl von Single Pass Instanced Rendering als Renderingpfad für eine Mixed Reality-Anwendung erheblich Zeit sparen, sowohl auf der CPU & GPU und ist die empfohlene Renderingkonfiguration.

Um jedoch einen einzelnen Draw-Aufruf für jedes Gitter für jedes Auge auszustellen, muss die GPU-Instanziierung von allen Shadern unterstützt werden. Durch die Instanziierung kann die GPU Aufrufe über beide Augen multiplex zeichnen. Die integrierten Unity-Shader sowie der MRTK Standard-Shader enthalten standardmäßig die erforderlichen Anweisungen zur Instancing im Shadercode. Wenn Sie jedoch benutzerdefinierte Shader für Unity schreiben, müssen diese Shader möglicherweise aktualisiert werden, um das Rendering von Single Pass Instanced zu unterstützen.

Beispielcode für benutzerdefinierten Shader

struct appdata
{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;

    UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};

struct v2f
{
    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;

    UNITY_VERTEX_OUTPUT_STEREO //Insert
};

v2f vert (appdata v)
{
    v2f o;

    UNITY_SETUP_INSTANCE_ID(v); //Insert
    UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Insert

    o.vertex = UnityObjectToClipPos(v.vertex);

    o.uv = v.uv;

    return o;
}

Qualitätseinstellungen

Unity stellt Voreinstellungen bereit, um die Qualität des Renderings für jeden Plattformendpunkt zu steuern. Diese Voreinstellungen steuern, welche grafischen Features aktiviert werden können, z. B. Schatten, Antialiasing, globale Beleuchtung und vieles mehr. Es wird empfohlen, diese Einstellungen zu verringern und die Anzahl der während des Renderings ausgeführten Berechnungen zu optimieren.

Schritt 1: Aktualisieren von Mixed Reality Unity-Projekten zur Verwendung der Einstellung "Niedrige Qualität "
Bearbeiten>Projekteinstellungen, und wählen Sie dann die Kategorie >Qualität Wählen Sie niedrige Qualität für die UWP-Plattform aus.

Schritt 2: Deaktivieren Sie für jede Unity-Szenendatei die globale Beleuchtung in Echtzeit.
Fenster>Rendering>Beleuchtungseinstellungen>Deaktivieren Sie globale Echtzeitbeleuchtung.

Tiefenpufferfreigabe (HoloLens)

Bei der Entwicklung für die Windows Mixed Reality-Plattform und insbesondere HoloLens kann die Aktivierung der Tiefenpufferfreigabe unter XR-Einstellungen bei der Hologrammstabilisierung hilfreich sein. Die Verarbeitung des Tiefenpuffers kann jedoch Leistungseinbußen verursachen, insbesondere bei Verwendung des 24-Bit-Tiefenformats. Daher wird dringend empfohlen , den Tiefenpuffer mit einer Genauigkeit von 16 Bit zu konfigurieren.

Wenn Z-Fighting aufgrund des niedrigeren Bitformats auftritt, vergewissern Sie sich, dass die weit entfernte Clipebene aller Kameras auf den niedrigsten möglichen Wert für die Anwendung festgelegt ist. Unity legt standardmäßig eine weit entfernte Clipebene von 1000m fest. Auf HoloLens ist eine weit entfernte Clipebene von 50 m in der Regel für die meisten Anwendungsszenarien mehr als ausreichend.

Hinweis

Bei Verwendung des 16-Bit-Tiefenformats funktionieren die erforderlichen Schablonenpuffereffekte nicht, da Unity in dieser Einstellung keinen Schablonenpuffer erstellt . Wenn Sie umgekehrt das 24-Bit-Tiefenformat auswählen, wird in der Regel ein 8-Bit-Schablonenpuffer erstellt, falls zutreffend auf der Endpunktgrafikplattform.

Wenn Sie eine Mask-Komponente verwenden, die den Schablonenpuffer erfordert, sollten Sie stattdessen RectMask2D verwenden, die keinen Schablonenpuffer erfordert und daher in Verbindung mit einem 16-Bit-Tiefenformat verwendet werden kann.

Hinweis

Um schnell zu ermitteln, welche Objekte in einer Szene nicht visuell in den Tiefenpuffer schreiben, kann das Hilfsprogramm Rendertiefepuffer unter den Editoreinstellungen im MRTK-Konfigurationsprofil verwendet werden.

Optimieren von Gitterdaten

Mit den Einstellungen zum Optimieren von Meshdaten wird versucht, nicht verwendete Vertexattribute in Ihrer Anwendung zu entfernen. Die Einstellung führt dies aus, indem sie jeden Shaderdurchlauf in jedem Material überläuft, das sich auf jedem Gitter im Build befindet. Dies ist gut für die Größe von Spieldaten und die Laufzeitleistung, kann jedoch die Buildzeiten erheblich beeinträchtigen.

Es wird empfohlen, diese Einstellung während der Entwicklung zu deaktivieren und während der Erstellung des "Master"-Builds erneut zu aktivieren. Die Einstellung finden Sie unterProjekteinstellungen>bearbeiten>Player>Andere Einstellungen>Gitterdaten optimieren.

Allgemeine Empfehlungen

Leistung kann eine mehrdeutige und sich ständig ändernde Herausforderung für Mixed Reality-Entwickler sein, und das Spektrum an Wissen zur Rationalisierung der Leistung ist groß. Es gibt jedoch einige allgemeine Empfehlungen, um zu verstehen, wie die Leistung für eine Anwendung angegangen werden kann.

Es ist nützlich, die Ausführung einer Anwendung in die Teile zu vereinfachen, die auf der CPU oder der GPU ausgeführt werden, und so zu ermitteln, ob eine App durch eine komponente begrenzt ist. Es kann zu Engpässen kommen, die sich sowohl auf Verarbeitungseinheiten als auch auf bestimmte Szenarien erstrecken, die sorgfältig untersucht werden müssen. Für den Einstieg ist es jedoch gut zu verstehen, wo eine Anwendung am häufigsten ausgeführt wird.

GPU-gebunden

Da die meisten Plattformen für Mixed Reality-Anwendungen stereoskopisches Rendering verwenden, ist es aufgrund der Art des Renderns eines "double-wide"-Bildschirms sehr üblich, GPU-gebunden zu sein. Darüber hinaus werden mobile Mixed Reality-Plattformen wie HoloLens oder Oculus Quest durch cpu-& GPU-Verarbeitungsleistung der Mobilen Klasse eingeschränkt.

Wenn Sie sich auf die GPU konzentrieren, gibt es in der Regel zwei wichtige Phasen, in denen eine Anwendung jeden Frame abschließen muss.

  1. Ausführen des Vertex-Shaders
  2. Ausführen des Pixelshaders (auch als Fragmentshader bezeichnet)

Ohne tief in das komplexe Feld der Computergrafik & Renderingpipelines einzutauchen, ist jede Shaderphase ein Programm, das auf der GPU ausgeführt wird, um Folgendes zu erzeugen.

  1. Vertexshader transformieren Gittervertices in Koordinaten im Bildschirmbereich (d. h. pro Vertex ausgeführter Code)
  2. Pixelshader berechnen die Farbe, die für ein bestimmtes Pixel- und Gitterfragment gezeichnet werden soll (d. h. Code wird pro Pixel ausgeführt).

In Bezug auf die Leistungsoptimierung ist es in der Regel fruchtbarer, sich auf die Optimierung der Vorgänge im Pixelshader zu konzentrieren. Eine Anwendung muss möglicherweise nur einen Würfel zeichnen, der nur 8 Scheitelpunkte aufweist. Der Bildschirmbereich, den der Cube einnimmt, liegt jedoch wahrscheinlich in der Größenordnung von Millionen von Pixeln. Daher kann das Reduzieren des Shadercodes um 10 Vorgänge erheblich mehr Arbeit sparen, wenn der Pixelshader reduziert wird als der Vertex-Shader.

Dies ist einer der Hauptgründe für die Verwendung des MRTK Standard-Shaders , da dieser Shader im Allgemeinen viel weniger Anweisungen pro Pixel & Scheitelpunkt ausführt als der Unity Standard-Shader, während vergleichbare ästhetische Ergebnisse erzielt werden.

CPU-Optimierungen GPU-Optimierungen
Logik der App-Simulation Renderingvorgänge
Vereinfachen der Physik Reduzieren von Beleuchtungsberechnungen
Vereinfachen von Animationen Reduzieren der Polygonanzahl & Anzahl von zeichnungsfähigen Objekten
Verwalten der Garbage Collection Reduzieren der Anzahl transparenter Objekte
Cacheverweise Vermeiden von Nachbearbeitungs-/Vollbildeffekten

Zeichnen von Aufrufen

Einer der häufigsten Fehler in Unity, der die Leistung verringert, ist das Klonen von Materialien zur Laufzeit. Wenn GameObjects dasselbe Material und/oder dasselbe Gitter haben, können sie mithilfe von Techniken wie statischer Batchverarbeitung, dynamischer Batchverarbeitung und GPU-Instanziierung in einzelne Zeichnungsaufrufe optimiert werden. Wenn jedoch die Eigenschaften eines Renderers zur Laufzeit vom Entwickler geändert werden, erstellt Unity eine Klonkopie des zugewiesenen Materials.

Wenn in einer Szene beispielsweise 100 Würfel vorhanden sind, kann ein Entwickler jedem zur Laufzeit eine eindeutige Farbe zuweisen. Der Zugriff auf renderer.material.color in C# bewirkt, dass Unity ein neues Material im Arbeitsspeicher für diesen speziellen Renderer/GameObject erstellt. Jeder der 100 Cubes verfügt über ein eigenes Material und kann daher nicht zu einem Draw-Aufruf zusammengeführt werden, sondern stattdessen zu 100 Draw-Aufrufanforderungen von der CPU an die GPU.

Um dieses Hindernis zu überwinden und dennoch eine eindeutige Farbe pro Würfel zuzuweisen, sollten Entwickler MaterialPropertyBlock nutzen.

private PropertyBlock m_PropertyBlock ;
private Renderer myRenderer;

private void Start()
{
     myRenderer = GetComponent<Renderer>();
     m_PropertyBlock = new MaterialPropertyBlock();
}

private void ChangeColor()
{
    // Creates a copy of the material once for this renderer
    myRenderer.material.color = Color.red;

    // vs.

    // Retains instancing capability for renderer
    m_PropertyBlock.SetColor("_Color", Color.red);
    myRenderer.SetPropertyBlock(m_PropertyBlock);
}

Unity-Leistungstools

Unity bietet hervorragende Leistungstools, die in den Editor integriert sind.

Wenn Sie den groben Leistungskonflikt zwischen einem Shader und einem anderen schätzen, ist es nützlich, jeden Shader zu kompilieren und die Anzahl der Vorgänge pro Shaderstufe anzuzeigen. Dazu wählen Sie ein Shaderobjekt aus, und klicken Sie auf die Schaltfläche Code kompilieren und anzeigen . Dadurch werden alle Shadervarianten kompiliert und Visual Studio mit den Ergebnissen geöffnet. Hinweis: Die erstellten Statistischen Ergebnisse können je nachdem variieren, welche Features für Materialien aktiviert wurden, die den angegebenen Shader verwenden. Unity kompiliert nur die Shadervarianten, die direkt im aktuellen Projekt verwendet werden.

Beispiel für Unity Standard-Shaderstatistiken

Unity Standard-Shaderstatistik 1

Beispiel für MRTK Standard-Shaderstatistiken

MRTK-Standard-Shaderstatistik 2

Weitere Informationen

Unity

Windows Mixed Reality

Oculus

Gitteroptimierung