Prestazioni — MRTK2

Introduzione

Il modo più semplice per razionalizzare le prestazioni è tramite la frequenza dei fotogrammi o il numero di volte in cui l'applicazione può eseguire il rendering di un'immagine al secondo. È importante soddisfare la frequenza dei frame di destinazione, come descritto dalla piattaforma di destinazione (ad esempio Windows Mixed Reality, Oculus e così via). Ad esempio, in HoloLens la frequenza dei fotogrammi di destinazione è 60 FPS. Le applicazioni a bassa frequenza di fotogrammi possono causare un deterioramento delle esperienze utente, ad esempio un peggioramento della stabilizzazione degli ologrammi, il rilevamento del mondo, il rilevamento delle mani e altro ancora. Per consentire agli sviluppatori di tenere traccia e ottenere una frequenza dei fotogrammi di qualità, Realtà mista Toolkit offre un'ampia gamma di strumenti e script.

Profiler visivo

Per tenere costantemente traccia delle prestazioni per tutta la durata dello sviluppo, è consigliabile visualizzare sempre un oggetto visivo con frequenza dei fotogrammi durante l'esecuzione & il debug di un'applicazione. Realtà mista Toolkit fornisce lo strumento di diagnostica di Visual Profiler che fornisce informazioni in tempo reale sull'utilizzo corrente di FPS e memoria nella visualizzazione applicazione. È possibile configurare Visual Profiler tramite le impostazioni del sistema di diagnostica in MrTK Profiles Inspector.

Inoltre, è particolarmente importante usare Visual Profiler per tenere traccia della frequenza dei fotogrammi durante l'esecuzione nel dispositivo anziché in esecuzione nell'editor di Unity o in un emulatore. I risultati delle prestazioni più accurati verranno illustrati durante l'esecuzione nel dispositivo con build di configurazione della versione.

Nota

Se si compila per Windows Mixed Reality, eseguire la distribuzione con le compilazioni di configurazione MASTER.

Interfaccia di Visual Profiler

Finestra Ottimizza

MrTK Optimize Window offre informazioni e strumenti di automazione che consentono agli sviluppatori di realtà mista di configurare l'ambiente per ottenere risultati ottimali e identificare potenziali colli di bottiglia nella scena & asset. Alcune configurazioni chiave in Unity consentono di ottenere risultati notevolmente più ottimizzati per i progetti di realtà mista.

In genere, queste impostazioni implicano configurazioni di rendering ideali per la realtà mista. Le applicazioni di realtà mista sono uniche rispetto allo sviluppo di grafica 3D tradizionale in quanto sono disponibili due schermi (ad esempio due occhi) per il rendering per l'intera scena.

Le impostazioni consigliate a cui si fa riferimento di seguito possono essere configurate automaticamente in un progetto Unity sfruttando la finestra di ottimizzazione di MRTK.

MRTK Optimize Window Settings

Unity Profiler

Unity Profiler è uno strumento utile per analizzare i dettagli delle prestazioni dell'applicazione a livello di fotogramma per fotogramma.

Tempo impiegato per la CPU

Esempio di grafo di Unity Profiler

Per mantenere una frequenza di fotogrammi confortevole (in genere 60 fotogrammi al secondo), le applicazioni devono ottenere un tempo di fotogrammi massimo di 16,6 millisecondi di tempo cpu. Per identificare il costo della funzionalità MRTK, Microsoft Realtà mista Toolkit contiene indicatori per i percorsi di codice del ciclo interno (per fotogramma). Questi marcatori usano il formato seguente per facilitare la comprensione delle funzionalità specifiche utilizzate:

[MRTK] className.methodName

Nota

Potrebbero essere presenti dati aggiuntivi dopo il nome del metodo. Viene usato per identificare funzionalità potenzialmente costose e eseguite in modo condizionale che possono essere evitate da piccole modifiche al codice dell'applicazione.

Esempio di gerarchia di Unity Profiler

In questo esempio la gerarchia è stata espansa per indicare che il metodo UpdateHandData della classe WindowsMixedRealityArticulatedHand usa 0,44 ms di tempo cpu durante il frame analizzato. Questi dati possono essere usati per determinare se un problema di prestazioni è correlato al codice dell'applicazione o da un'altra parte del sistema.

È consigliabile che gli sviluppatori instrumentno il codice dell'applicazione in modo simile. Le aree principali dello stato attivo per la strumentazione del codice dell'applicazione si trovano all'interno dei gestori eventi perché questi metodi vengono addebitati al ciclo di aggiornamento MRTK man mano che vengono generati gli eventi. Tempi di fotogrammi elevati all'interno del ciclo di aggiornamento MRTK possono essere indicativi di codice costoso nei metodi del gestore eventi.

Single-Pass rendering con istanza

La configurazione di rendering predefinita per XR in Unity è Multi-pass. Questa impostazione indica a Unity di eseguire l'intera pipeline di rendering due volte, una per ogni occhio. Questa opzione può essere ottimizzata selezionando rendering con istanza a passaggio singolo . Questa configurazione sfrutta le matrici di destinazione di rendering per essere in grado di eseguire una singola chiamata di disegno che le istanze nella destinazione di rendering appropriata per ogni occhio. Inoltre, questa modalità consente di eseguire tutto il rendering in una singola esecuzione della pipeline di rendering. Pertanto, la selezione del rendering con istanza a passaggio singolo come percorso di rendering per un'applicazione di realtà mista può risparmiare tempo sostanziale sia sulla CPU & GPU che sulla configurazione di rendering consigliata.

Tuttavia, per eseguire una singola chiamata di disegno per ogni mesh a ogni occhio, l'istanza della GPU deve essere supportata da tutti gli shader. La creazione di istanze consente alla GPU di disegnare più volte le chiamate su entrambi gli occhi. Gli shader predefiniti di Unity e lo shader Standard MRTK contengono per impostazione predefinita le istruzioni di creazione di istanze necessarie nel codice dello shader. Se si scrivono shader personalizzati per Unity, potrebbe essere necessario aggiornare questi shader per supportare il rendering con istanza a passaggio singolo.

Codice di esempio per lo shader personalizzato

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;
}

Impostazioni di qualità

Unity offre set di impostazioni per controllare la qualità del rendering per ogni endpoint della piattaforma. Questi set di impostazioni controllano quali funzionalità grafiche possono essere abilitate, ad esempio ombre, anti-aliasing, illuminazione globale e altro ancora. È consigliabile ridurre queste impostazioni e ottimizzare il numero di calcoli eseguiti durante il rendering.

Passaggio 1: Aggiornare i progetti Unity di realtà mista per usare l'impostazione Livello di bassa qualità
Redigere>Impostazioni progetto, quindi selezionare la categoria >Qualità selezionare Bassa qualità per la piattaforma UWP

Passaggio 2: Per ogni file di scena di Unity, disabilitare l'illuminazione globale in tempo reale
Finestra>Interpretazione>Impostazioni di> illuminazioneDeselezionare Illuminazione globale in tempo reale

Condivisione del buffer di profondità (HoloLens)

Se si sviluppa per la piattaforma Windows Mixed Reality e in particolare HoloLens, l'abilitazione della condivisione del buffer di profondità in Impostazioni XR può essere utile per la stabilizzazione degli ologrammi. Tuttavia, l'elaborazione del buffer di profondità può comportare un costo delle prestazioni, in particolare se si usa il formato di profondità a 24 bit. È quindi consigliabile configurare il buffer di profondità con precisione a 16 bit.

Se il combattimento z si verifica a causa del formato in bit inferiore, verificare che il piano di clip lontano di tutte le fotocamere sia impostato sul valore più basso possibile per l'applicazione. Unity imposta per impostazione predefinita un piano di clip lontano di 1000 m. In HoloLens, un piano di clip lontano di 50 m è in genere più che sufficiente per la maggior parte degli scenari di applicazione.

Nota

Se si usa il formato di profondità a 16 bit, gli effetti richiesti dal buffer degli stencil non funzioneranno perché Unity non crea un buffer stencil in questa impostazione. Se si seleziona il formato di profondità a 24 bit al contrario, in genere viene creato un buffer di stencil a 8 bit, se applicabile nella piattaforma grafica degli endpoint.

Se si usa un componente Mask che richiede il buffer degli stencil, prendere in considerazione l'uso di RectMask2D , che non richiede il buffer degli stencil e quindi può essere usato in combinazione con un formato di profondità a 16 bit.

Nota

Per determinare rapidamente quali oggetti in una scena non scrivono visivamente nel buffer di profondità, è possibile usare l'utilità Render Depth Buffer nel Editor Settings nel profilo di configurazione MRTK.

Ottimizzare i dati mesh

Le impostazioni Ottimizza dati mesh tentano di rimuovere gli attributi dei vertici inutilizzati all'interno dell'applicazione. L'impostazione esegue questa operazione eseguendo ogni passaggio dello shader in ogni materiale presente in ogni mesh della compilazione. Ciò è utile per le dimensioni dei dati del gioco e le prestazioni di runtime, ma può ostacolare drasticamente i tempi di compilazione.

È consigliabile disabilitare questa impostazione durante lo sviluppo e riabilitare durante la creazione della compilazione "Master". L'impostazione è disponibile in Modifica>impostazioni> progettoPlayer>Altre impostazioni Ottimizza dati>mesh.

Raccomandazioni generali

Le prestazioni possono essere una sfida ambigua e in continua evoluzione per gli sviluppatori di realtà mista e lo spettro delle conoscenze per razionalizzare le prestazioni è vasto. Esistono tuttavia alcune raccomandazioni generali per comprendere come affrontare le prestazioni per un'applicazione.

È utile semplificare l'esecuzione di un'applicazione nelle parti eseguite sulla CPU o sulla GPU e quindi identificare se un'app è delimitata da uno dei due componenti. Possono esserci colli di bottiglia che si estendono sia nelle unità di elaborazione che in alcuni scenari univoci che devono essere esaminati attentamente. Tuttavia, per iniziare, è consigliabile comprendere dove un'applicazione viene eseguita per la maggior parte del tempo.

GPU delimitata

Poiché la maggior parte delle piattaforme per le applicazioni di realtà mista usa il rendering stereoscopico, è molto comune essere delimitati da GPU a causa della natura del rendering di uno schermo "a doppia larghezza". Inoltre, le piattaforme di realtà mista per dispositivi mobili come HoloLens o Oculus Quest saranno limitate dalla cpu di classe mobile & dalla potenza di elaborazione GPU.

Quando ci si concentra sulla GPU, in genere ci sono due fasi importanti che un'applicazione deve completare ogni fotogramma.

  1. Eseguire il vertex shader
  2. Eseguire il pixel shader (noto anche come fragment shader)

Senza approfondire il complesso campo della grafica artificiale & delle pipeline di rendering, ogni fase dello shader è un programma eseguito nella GPU per produrre quanto segue.

  1. I vertex shader trasformano i vertici della mesh in coordinate nello spazio dello schermo (ad esempio codice eseguito per vertice)
  2. I pixel shader calcolano il colore da disegnare per un determinato pixel e frammento di mesh (ad esempio il codice eseguito per pixel)

Per quanto riguarda l'ottimizzazione delle prestazioni, in genere è più utile concentrarsi sull'ottimizzazione delle operazioni nel pixel shader. Un'applicazione potrebbe dover disegnare solo un cubo che sarà solo 8 vertici. Tuttavia, lo spazio sullo schermo occupato dal cubo è probabilmente nell'ordine di milioni di pixel. Pertanto, riducendo il codice dello shader, ad esempio 10 operazioni, è possibile risparmiare molto più lavoro se ridotto sul pixel shader rispetto al vertex shader.

Questo è uno dei motivi principali per sfruttare lo shader Standard MRTK perché questo shader esegue in genere molte meno istruzioni per pixel & vertice rispetto allo shader Standard Unity, ottenendo al tempo stesso risultati estetici confrontabili.

Ottimizzazioni CPU Ottimizzazioni GPU
Logica di simulazione delle app Operazioni di rendering
Semplificare la fisica Ridurre i calcoli di illuminazione
Semplificare le animazioni Ridurre il numero di poligoni & # di oggetti disegnabili
Gestire Garbage Collection Ridurre il numero di oggetti trasparenti
Riferimenti alla cache Evitare effetti post-elaborazione/schermo intero

Creazione di istanze di chiamate

Uno degli errori più comuni in Unity che riduce le prestazioni è la clonazione di materiali in fase di esecuzione. Se gameobject condividono lo stesso materiale e/o sono la stessa mesh, possono essere ottimizzati in singole chiamate di disegno tramite tecniche come batch statico, batch dinamico e istanze GPU. Tuttavia, se le proprietà di modifica del materiale di un renderer vengono modificate in fase di esecuzione, Unity creerà una copia clone del materiale assegnato.

Ad esempio, se sono presenti 100 cubi in una scena, uno sviluppatore potrebbe voler assegnare un colore univoco a ognuno in fase di esecuzione. L'accesso di renderer.material.color in C# farà in modo che Unity crei un nuovo materiale in memoria per questo particolare renderer/GameObject. Ognuno dei 100 cubi avrà il proprio materiale e quindi non può essere unito in un'unica chiamata di disegno, ma diventerà invece 100 richieste di chiamata di disegno dalla CPU alla GPU.

Per superare questo ostacolo e assegnare ancora un colore univoco per cubo, gli sviluppatori devono sfruttare MaterialPropertyBlock.

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);
}

Strumenti per le prestazioni di Unity

Unity offre ottimi strumenti per le prestazioni integrati nell'editor.

Se si stima il compromesso tra prestazioni approssimative tra uno shader e un altro, è utile compilare ogni shader e visualizzare il numero di operazioni per ogni fase dello shader. Questa operazione può essere eseguita selezionando un asset shader e facendo clic sul pulsante Compila e mostra codice . Verranno compilate tutte le varianti dello shader e verrà aperto Visual Studio con i risultati. Nota: i risultati delle statistiche prodotti possono variare a seconda delle funzionalità abilitate per i materiali che usano lo shader specificato. Unity compilerà solo le varianti dello shader usate direttamente nel progetto corrente.

Esempio di statistiche shader Standard Unity

Statistiche shader di Unity Standard 1

Esempio di statistiche degli shader Standard MRTK

MRTK Standard Shader Statistics 2

Vedere anche

Unità

Windows Mixed Reality

Oculus

Ottimizzazione mesh