Entwickeln

Dynamische Auflösung

Aktualisiert: 18.02.2025

Übersicht

Dynamische Auflösung ist eine Funktion im Horizon OS, mit der Apps ihre Render-Größe in Einzelbildern automatisch erhöhen können, wenn die GPU nicht komplett ausgelastet ist, oder die Render-Größe reduzieren können, wenn die GPU komplett ausgelastet ist.
Apps mit dynamischer Auflösung stellen also automatisch ein Gleichgewicht zwischen der Wahrung der Bildwiederholrate und einer optimalen Rendering-Auflösung her.
  • In Szenen, die die GPU nicht komplett auslasten (z. B. ein einfacher Korridor), erhöht die dynamische Auflösung die Render-Größe, um die Grafikqualität zu verbessern.
  • In Szenen, die die GPU komplett auslasten (z. B. Aussichtspunkte mit Rundumblick, Charakter-Rendering in Zwischensequenzen), reduziert die dynamische Auflösung die Render-Größe soweit wie nötig, um eine passende Bildwiederholrate sicherzustellen.
Auf Meta Quest 2 und neueren Headsets ist das Aktivieren der dynamischen Auflösung außerdem eine Voraussetzung, um die höchsten Grafikprozessorauslastungen freizuschalten. Die Grafikprozessorauslastung 5 ist auf Meta Quest 3 beispielsweise verfügbar, wenn die dynamische Auflösung aktiviert ist.

Funktionsweise

Szenen in einer App sind oft unterschiedlich komplex, was es schwierig macht, für jede einzelne zu optimieren. Die dynamische Auflösung bietet hier Abhilfe, indem sie den gerenderten Viewport auf der Grundlage der GPU-Auslastung skaliert, um die angestrebte Bildrate beizubehalten.
Wenn in der App Einzelbilder verloren gehen, schaltet die dynamische Auflösung auf eine niedrigere Auflösung um. Dies hilft, veraltete Einzelbilder zu reduzieren und die gewünschte Bildrate in Szenen mit hoher GPU-Auslastung aufrechtzuerhalten.
Wenn die App die GPU nicht voll ausnutzt, schaltet die dynamische Auflösung auf eine höhere Auflösung um, um die Bildqualität bei gleichbleibender Bildrate zu verbessern.
Um zu vermeiden, dass die Augentexturen jedes Mal neu zugewiesen werden, wenn die empfohlene Auflösung geändert wird, werden die Augentexturen einmal mit der maximalen Auflösung zugewiesen. Anschließend skaliert die App den Viewport auf die empfohlene Auflösung und vermeidet so das Rendern außerhalb des Viewports.
Mit der dynamischen Auflösung kann Horizon OS auch höhere Grafikprozessorauslastungen für die ausgeführte App bereitstellen. Diese Grafikprozessorauslastungen sind nur zusammen mit der dynamischen Auflösung verfügbar, da sie mehr Energie verbrauchen und daher auch mehr Wärme erzeugen, wodurch es leichter passieren kann, dass das Temperaturlimit des Headsets erreicht wird.
Mit aktivierter dynamischer Auflösung kann Horizon OS die Render-Größe deiner App bei zu hohen Temperaturen dynamisch drosseln, um das Temperaturlimit einzuhalten, ohne Einzelbilder auszulassen. Da eine einheitliche Bildwiederholrate ein für komfortable VR-Erlebnisse unverzichtbar ist, stellt Horizon OS diese höheren Grafikprozessorauslastungen nur zur Verfügung, wenn die dynamische Auflösung aktiviert ist.

Voraussetzungen

Bevor du mit diesem Tutorial fortfährst, solltest du die in den folgenden Abschnitten beschriebenen Einrichtungsschritte ausführen:

Projekteinrichtung

OVRCameraRig zur Szene hinzufügen

Falls dein Unity-Projekt kein OVRCameraRig-Objekt enthält, führe die folgenden Schritte aus, um es hinzuzufügen:
Meta XR Core SDK enthält das Prefab OVRCameraRig, das als XR-Ersatz für die standardmäßige Main Camera von Unity dient.
Füge OVRCameraRig mit diesen Schritten zu deiner Szene hinzu:
  1. Klicke in der Projekthierarchie mit der rechten Maustaste auf Main Camera und wähle Delete aus.
  2. Wähle unter dem Tab ProjectAll Prefabs aus, suche nach OVRCameraRig und ziehe dann das Prefab OVRCameraRig in die Projekthierarchie.
  3. Wähle OVRCameraRig in der Hierarchy aus.
  4. Wähle im Fenster Inspector unter der Komponente OVR Manager dein Headset unter Target Devices aus.

Option für dynamische Auflösung auswählen

Stelle im OVRCameraRig-Objekt sicher, dass das Kästchen Enable Dynamic Resolution aktiviert ist. Gib den minimalen und maximalen Skalierungsfaktor an.

Implementierung

Dynamische Auflösung zur Laufzeit aktivieren/deaktivieren

Mit folgendem Aufruf kannst du die dynamische Auflösung zur Laufzeit aktivieren und deaktivieren:
OVRManager.instance.enableDynamicResolution = value;
Wenn du die dynamische Auflösung deaktivierst, kannst du manuell festlegen, in welcher Auflösung gerendert werden soll, und zwar wie folgt:
XRSettings.renderViewportScale = <scaling factor>;

Ändern der Auflösung der Augentextur

Wenn die App startet, werden die Augentexturen mit dem in OVRManager angegebenen Skalierungsfaktor für die maximale Auflösung zugewiesen. Durch die Deaktivierung der dynamischen Auflösung werden die Augentexturen nicht auf 1,0x neu zugewiesen (sie bleiben auf dem in OVRManager eingestellten maximalen Skalierungsfaktor). Wenn du die Augentexturen verkleinern oder vergrößern möchtest, kannst du Folgendes tun:
XRSettings.eyeTextureResolutionScale = <scaling factor>;

Best Practices

Kompromisse

Die dynamische Auflösung kann ein hervorragendes Tool zur einfachen Optimierung deiner App in Abhängigkeit vom Inhalt deiner Szenen sein. Es ist jedoch wichtig zu wissen, welche Kompromisse du mit der Aktivierung dieser Funktion eingehst:
  • Beim Start wird der Eye-Render-Buffer unter Verwendung des maximalen Skalierungsfaktors der Auflösung zugewiesen. Dies bedeutet, dass deine App mehr Speicher belegt, wenn du für den maximalen Skalierungsfaktor der Auflösung einen höheren Wert als 1,0x angibst.
  • Die Festlegung eines niedrigen minimalen Skalierungsfaktors der Auflösung kann zu Qualitätseinbußen führen, wenn die Framerate nicht aufrechterhalten werden kann.
Wenn du dir die Kosten für zusätzlichen Speicher leisten kannst, kannst du den maximalen Skalierungsfaktor erhöhen, um die Bildqualität in Szenen mit geringer GPU-Auslastung zu verbessern. Wenn du den minimalen Skalierungsfaktor für die Auflösung festlegst, solltest du jedoch vorsichtig sein. Eine zu hohe Einstellung kann in Szenen mit hoher GPU-Auslastung zu Bildaussetzern führen, während eine zu niedrige Einstellung bei steigender GPU-Auslastung zu spürbaren Qualitätseinbußen führen kann. Diese Beeinträchtigung ist in actiongeladenen Szenen mit Effekten weniger offensichtlich und macht sich eher in langsameren Sequenzen bemerkbar.

Profile für Apps mit dynamischer Auflösung erstellen

Wenn du ein Profil für deine App erstellst, solltest du die dynamische Auflösung unbedingt deaktivieren, da sich diese Funktion auf die Leistung der App auswirkt.
Denke daran, dass die dynamische Auflösung nicht jedes Leistungsproblem lösen kann. Die dynamische Auflösung verringert die Auflösung deiner App, wenn diese unzureichend optimiert ist, um die Bildrate aufrechtzuerhalten. Um eine hohe Auflösung bei der gewünschten Bildrate aufrechtzuerhalten, solltest du immer die richtigen Tools für die Profilerstellung verwenden und deine App vollständig optimieren, bevor du die Funktion aktivierst.
Und schließlich muss deine App auch die Anforderungen an die Leistung erfüllen, was verhindert, dass Anwendungen die meiste Zeit mit einer niedrigen Auflösung ausgeführt werden. Hier findest du nähere Informationen zur entsprechenden VRC.

Dynamic Foveated Rendering

Die dynamische Auflösung unterstützt die Aktivierung von Dynamic Foveated Rendering (sowohl Fixed Foveated Rendering (FFR) als auch Eye Tracked Foveated Rendering (ETFR)). Die Runtime wird zuerst versuchen, die Foveated-Rendering-Stufe zu erhöhen, bevor sie die Auflösung herabsetzt, wenn die GPU-Auslastung zu hoch wird.
In den VrApi-Protokollen findest du Angaben zur empfohlenen Runtime-Auflösung:
adb logcat -s VrApi
Hier ein Ausgabebeispiel:
FPS=65/72,Prd=50ms,Tear=0,Early=12,Stale=12,Stale2/5/10/max=1/0/0/2,VSnc=0,Lat=-1,Fov=2D,CPU4/GPU=4/4,1478/525MHz,OC=FF,TA=0/0/0,SP=N/N/N,Mem=2092MHz,Free=8191MB,PLS=0,Temp=26.5C/0.0C,TW=1.93ms,App=10.28ms,GD=0.00ms,CPU&GPU=20.74ms,LCnt=3(DR72,LM3),GPU%=0.92,CPU%=0.20(W0.28),DSF=1.00,CFL=16.86/20.74,LD=1,SF=1.03
Wenn du dir die GPU-Auslastung (GPU%) ansiehst, wirst du feststellen, dass sie ziemlich hoch wird. Die Laufzeit wird einen niedrigeren Skalierungsfaktor (SF) empfehlen, um die Anzahl der veralteten Einzelbilder (Stale) zu reduzieren und die GPU-Auslastung zu verringern. Der SF ist ein Multiplikationsfaktor, der auf die standardmäßig empfohlene Eye-Render-Buffer-Auflösung des Systems aufgeschlagen wird.

Bekannte Probleme

Derzeit bekannte Probleme werden in späteren Versionen von Unity und Meta XR SDK behoben. Wenn du kein Upgrade auf neuere Versionen durchführen kannst, findest du hier einige Korrekturen, die du lokal anwenden kannst.

Neuzuweisung von TempRT führt zu OOM (in Unity 6000.0.1f1+ und 2022.3.15f1+ behoben)

Temporäre Rendering-Ziele werden neu zugewiesen, wenn ein Wert für XRSettings.renderViewportScale zugewiesen wird. Dies kann möglicherweise zu einem Speicherplatzfehler führen. Gehe wie folgt vor, um zu vermeiden, dass tempRT neu zugewiesen wird:
Ändere in „XRSystem.cs“ (Unity 2021) in „UpdateCameraData()“ die folgenden Zeilen:
//baseCameraData.cameraTargetDescriptor.width = baseCameraData.pixelWidth;
//baseCameraData.cameraTargetDescriptor.height = baseCameraData.pixelHeight;
baseCameraData.cameraTargetDescriptor.width = xr.renderTargetDesc.width;
baseCameraData.cameraTargetDescriptor.height = xr.renderTargetDesc.height;
baseCameraData.cameraTargetDescriptor.useDynamicScale = true;
Dadurch wird sichergestellt, dass nicht alle Render-Durchgänge, die zur Konfiguration den cameraTargetDescriptor verwenden, ihre Auflösung ändern, wenn sich der Viewport ändert. Wenn du die dynamische Skalierung für den Deskriptor aktivierst, wird auch für alle temporären Rendering-Ziele, die diesen Deskriptor verwenden, das Flag für dynamische Skalierung gesetzt.
Wenn du Unity 2022+ und die Universal Render Pipeline verwendest, musst du diesen Patch aus der Universal Render Pipeline von Unity einspielen oder eine Synchronisierung auf eine URP-Version größer oder gleich 14.0.9 durchführen. Falls du einen Oculus-VR-Branch von URP verwendest, musst du dennoch eine Synchronisierung auf eine URP-Version größer oder gleich 14.0.9 durchführen.
Die andere Änderung wird in „OVRManager.cs“ vorgenommen. Anstatt nur die XRSettings.renderViewportScale festzulegen, legen wir auch die Breite und Höhe von ScalableBufferManager fest:
XRSettings.renderViewportScale = scalingFactor;
ScalableBufferManager.ResizeBuffers(scalingFactor, scalingFactor); // add this line to also scale the temporary render targets WITHOUT reallocating them.

Zusätzliche RP beim Skalierungsfaktor != 1 (in Unity 6000.0.1f1+, 2022.3.22f1+ und 2021.3.36f1+ behoben)

Wenn deine App direkt auf das XR-Ziel rendert (wenn deine Pipeline keine Zwischendurchgänge hat, die zur Kamera rendern), erzwingt URP einen zusätzlichen Zwischenrendering-Durchgang, falls der Skalierungsfaktor nicht 1 ist, was zu Leistungseinbußen führt. Du kannst Folgendes tun, um den zusätzlichen Rendering-Durchgang zu vermeiden:
Du kannst in UniversalRenderer.cs in RequiresIntermediateColorTexture() die Bedingung auskommentieren, die den Zwischendurchgang !cameraData.isDefaultViewport erzwingt. Unity rendert bei einem Skalierungsfaktor != 1 nun direkt auf das XR-Ziel, aber der Viewport wird nicht korrekt festgelegt. Du kannst dies beheben, indem du in deinem letzten Rendering-Durchgang in Execute einen SetViewport-Befehl hinzufügst, kurz bevor du „context.ExecuteCommandBuffer(cmd);“ aufrufst:
Rect rect = new Rect() {x=0,y=0, width=renderingData.cameraData.pixelWidth, height=renderingData.cameraData.pixelHeight };
cmd.SetViewport(rect);

Bildschirmverzerrung in Unity 6000.0.22f1 bis 6000.0.24f1 (behoben in Unity 6000.0.25f1+)

Die Aktivierung der dynamischen Auflösung führt in 6000.0.22f1, 6000.0.23f1 und 6000.0.24f1 zu Bildschirmverzerrungen. Wir empfehlen, ein Update auf Version 6000.0.25f1 oder höher durchzuführen.