Compreender o desempenho da realidade mista

Este artigo é uma introdução para compreender a importância do desempenho da sua aplicação Mixed Reality. A experiência do utilizador pode ser muito degradada se a sua aplicação não for executada à taxa de fotogramas ideal. Os hologramas serão instáveis e o controlo principal do ambiente será impreciso, o que levará a uma má experiência para o utilizador. O desempenho tem de ser considerado uma funcionalidade de primeira classe para o desenvolvimento de realidade mista e não uma tarefa polida.

Os valores de framerate de desempenho para cada plataforma de destino estão listados abaixo.

Plataforma Taxa de Fotogramas de Destino
HoloLens 60 FPS
PCs Windows Mixed Reality Ultra 90 FPS
PCs Windows Mixed Reality 60 FPS

A arquitetura abaixo descreve as melhores práticas para atingir as taxas de fotogramas de destino. Para obter sugestões sobre como medir e melhorar a taxa de fotogramas no ambiente do Unity, recomendamos que leia o artigo Recomendações de desempenho do Unity

Compreender os estrangulamentos de desempenho

Se a sua aplicação tiver uma taxa de fotogramas de desempenho inferior, o primeiro passo é analisar e compreender onde a sua aplicação é intensiva em termos computacionais. Existem dois processadores principais responsáveis pelo trabalho para compor a sua cena: a CPU e a GPU, cada um a processar diferentes aspetos da sua aplicação Mixed Reality. Os três principais locais onde podem ocorrer estrangulamentos são:

  1. Thread de Aplicação – CPU – responsável pela lógica da sua aplicação, incluindo o processamento de entradas, animações, física e outra lógica de aplicação.
  2. Thread de Composição – CPU para GPU – responsável por submeter as chamadas de sorteio para a GPU. Quando a aplicação pretende compor um objeto, como um cubo ou modelo, este thread envia um pedido à GPU para realizar as operações.
  3. GPU – normalmente processa o pipeline gráfico da sua aplicação para transformar dados 3D (modelos, texturas, etc.) em píxeis. Em última análise, produz uma imagem 2D para submeter para o ecrã do seu dispositivo.

Duração de uma Moldura

Geralmente, as aplicações do HoloLens estarão vinculadas à GPU, mas nem sempre. Utilize as ferramentas e técnicas abaixo para compreender onde a sua aplicação específica está com estrangulamento.

Como analisar a sua aplicação

Existem muitas ferramentas que lhe permitem compreender o perfil de desempenho e potenciais estrangulamentos na sua aplicação de realidade mista.

Seguem-se algumas ferramentas comuns para o ajudar a recolher informações aprofundadas de criação de perfis para a sua aplicação:

Como criar perfis em qualquer ambiente

Uma forma de determinar se a sua aplicação está vinculada à GPU ou à CPU é reduzir a resolução da saída de destino de composição. Ao reduzir o número de píxeis a calcular, reduzirá a carga da GPU. O dispositivo será composto com uma textura mais pequena e, em seguida, up-sample para apresentar a sua imagem final.

Depois de reduzir a resolução de composição, se:

  1. A taxa de frames da aplicação aumenta e, em seguida, é provável que esteja Vinculado à GPU
  2. Taxa de frames da aplicação inalterada e, em seguida, é provável que esteja Vinculado à CPU

Nota

O Unity permite modificar facilmente a resolução de destino de composição da sua aplicação no runtime através da propriedade XRSettings.renderViewportScale . A imagem final apresentada no dispositivo tem uma resolução fixa. A plataforma irá provar a saída de resolução inferior para criar uma imagem de resolução superior para composição em ecrãs.

UnityEngine.XR.XRSettings.renderScale = 0.7f;

Como melhorar a sua aplicação

Recomendações de desempenho da CPU

Geralmente, a maioria dos trabalhos numa aplicação de realidade mista na CPU envolve fazer a "simulação" da cena e processar a lógica da aplicação. As seguintes áreas são direcionadas para otimização:

  • Animações
  • Física
  • Alocações de memória
  • Algoritmos complexos (ou seja, kinemática inversa, localização de caminhos)

Recomendações de desempenho da GPU

Compreender a largura de banda vs. taxa de preenchimento

Ao compor uma moldura na GPU, uma aplicação está vinculada por largura de banda de memória ou taxa de preenchimento.

  • A largura de banda de memória é a taxa de leituras e escritas que a GPU pode fazer a partir da memória
    • Para identificar limitações de largura de banda, reduza a qualidade da textura e verifique se a velocidade de fotogramas melhorou.
    • Para identificar as limitações da taxa de preenchimento, reduza a resolução do ecrã e veja se a taxa de fotogramas melhora.

Nota

Se estiver a trabalhar com o Unity, veja as nossas recomendações de desempenho da GPU específicas do Unity. - No Unity, utilize a propriedade XRSettings.renderViewportScale

Geralmente, a largura de banda da memória envolve otimizações para:

  1. Resoluções de textura mais baixas
  2. Utilizar menos texturas (normais, especulares, etc.)

A taxa de preenchimento concentra-se na redução do número de operações que têm de ser calculadas para um pixel composto final, incluindo:

  1. Número de objetos a compor/processar
  2. Número de operações por sombreado
  3. Número de fases de GPU para o resultado final (sombreados de geometria, efeitos pós-processamento, etc.)
  4. Número de píxeis a compor (resolução do ecrã)

Reduzir a contagem de polígonos

As contagens de polígonos mais elevadas resultam em mais operações para a GPU, pelo que reduzir o número de polígonos na cena reduz o tempo de composição. Existem outros fatores que tornam o sombreado da geometria caro, mas a contagem de polígonos é a métrica mais simples para determinar quanto trabalho será necessário para compor uma cena.

Limite de desmaiado

A sobrecarga elevada ocorre quando vários objetos são compostos, mas não são apresentados no ecrã, uma vez que estão ocultos por um objeto ocluso. Imagine olhar para uma parede que tem objetos atrás dela. Toda a geometria seria processada para composição, mas apenas a parede opaca tem de ser composta, o que resulta em operações desnecessárias.

Sombreados

Os sombreados são pequenos programas que são executados na GPU e efetuam dois passos importantes na composição:

  1. Determinar que vértices devem ser desenhados e onde estão no espaço no ecrã (o sombreado do Vértice)
    • O sombreado de Vértice é executado por vértice para cada malha.
  2. Determinar a cor de cada píxel (o sombreado de Pixel)
    • O sombreado pixel é executado por pixel e composto pela geometria para a textura de composição de destino.

Normalmente, os sombreados fazem muitas transformações e cálculos de iluminação. Embora modelos de iluminação complexos, sombras e outras operações possam gerar resultados fantásticos, também têm um preço. Reduzir o número de operações calculadas em sombreados pode reduzir consideravelmente o trabalho necessário para a GPU por frame.

Recomendações de codificação do Shader
  • Utilizar filtragem bilinear, sempre que possível
  • Reorganizar expressões para utilizar intrínsecos MAD para multiplicar e adicionar ao mesmo tempo
  • Pré-calcule o máximo possível na CPU e transmita o máximo de constantes para o material
  • Favoreça as operações de movimentação do sombreado de píxeis para o sombreado de vértice
    • Geralmente, o número de vértices é muito menor do que o número de pixéis (720p é 921.600 píxeis, 1080p é de 2.073.600 píxeis, etc.)

Remover fases de GPU

Os efeitos pós-processamento podem ser dispendiosos e aumentar a taxa de preenchimento da sua aplicação, incluindo técnicas anti-aliasing como a MSAA. No HoloLens, recomendamos que evite estas técnicas e fases adicionais de sombreado, como geometria, casco e sombreados de computação.

Recomendações de memória

As operações de alocação e desalocação de memória excessivas podem resultar num desempenho inconsistente, molduras congeladas e outro comportamento prejudicial. É especialmente importante compreender as considerações de memória ao desenvolver no Unity, uma vez que a gestão da memória é controlada pelo recoletor de lixo.

Agrupamento de objetos

O agrupamento de objetos é uma técnica popular para reduzir o custo das alocações e desalocações contínuas de objetos. Isto é feito ao alocar um grande conjunto de objetos idênticos e reutilizar instâncias inativas e disponíveis deste conjunto em vez de gerar e destruir objetos constantemente ao longo do tempo. Os conjuntos de objetos são ótimos para componentes reutilizáveis que têm duração variável durante uma aplicação.

Ver também