Pesquisar em Unity

Uma cena, 10 otimizações gráficas para desenvolvedores de console

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 os apresentou na Unite), and our demo team. These optimizations were made to an especially difficult scene to ensure smooth 30fps performance.

Qualidade AAA com os Pipelines de Renderização Scriptáveis Unity

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 Pipeline de Renderização de Alta Definição (HDRP) which offers all of the features that you'd expect from a modern, AAA quality, high fidelity renderer, while the Pipeline de Renderização Scriptável Leve (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 disponíveis para você in the Asset Store.

Um importante passo de otimização para chegar a 1080p a 30fps (ou melhor) em consoles

O objetivo da demonstração era oferecer uma experiência interativa permitindo aos utilizadores passear por esse ambiente e experimentá-lo de uma forma que fosse familiar na perspectiva de jogos tradicionais AAA. Especificamente, queríamos mostrar BOTD no Xbox One e PS4. Nossos requisitos de desempenho eram de 10 qps a 30 qps ou melhor.

Como é uma demonstração e não é um jogo completo, o foco principal das otimizações estava na renderização.

Geralmente, o desempenho do BOTD é bastante consistente, pois não há cenas em que, por exemplo, de repente aparecem milhares de partículas ou vários personagens animados.

Para começar, Rob e a equipe de demonstração descobriram a visualização que estava apresentando o pior desempenho em termos de utilização da GPU. Aqui está uma captura de tela::

console scriptable rendering pipeline

O que acontece na cena é praticamente constante; o que varia é o que está na visão da câmera. A economia nessa cena pode resultar em melhor desempenho para toda a demonstração.

A razão para o mau desempenho dessa cena é que é a visão externa do nível e você olha para o centro, de modo que a maioria dos recursos está no campo de visão da câmera (frustum). Isso resulta em inúmeras draw calls.

Em resumo, essa cena foi renderizada da seguinte maneira:

  • Com HDRP
  • A maioria das texturas criadas por artistas gráficos são mapas entre 1K e 2K, alguns 4K.
  • Baked Oclusion e Baked GI são usadas para iluminação indireta, e uma fonte de luz dinâmica única é usada para a luz direta do sol.
  • Emite alguns milhares de draw calls em qualquer ponto (draw calls e calculos de envio de shaders)
  • No início da otimização, a visualização estava vinculada à GPU no PS4 Pro em cerca de 45 milissegundos.
O que o Frame da GPU mostrou antes da otimização

No início da otimização, Rob e a equipe examinaram o frame da GPU, passo a passo, e viram o seguinte desempenho:

  • The Gbuffer was at 11ms (you can find a description of the Gbuffer layouts for HDRP in neste post by Unity lead graphics developer Sebastien Lagarde)
  • Os vetores de movimento e a oclusão de ambiente em espaço de tela foram bastante rápidos, a 0,25 e 0,6 ms respectivamente
  • Os mapas de sombra da projeção de sombras direcional com luzes dinâmicas chegavam a incríveis 13.9ms
  • A iluminação diferida estava a 4.9ms
  • A dispersão atmosférica estava a 6,6ms

Assim estava o frame da GPU do princípio ao fim:

console GPU frame

Como você pode ver, a equipe ficou em 45 milissegundos. As duas linhas verticais laranja indicam onde ele deve ficar para atingir 30 fps ou 60 fps respetivamente.

10 maneiras de otimizar a renderização do Book of the Dead

Controlar a contagem de lotes

O desempenho da CPU não foi um grande problema para a equipe porque o BOTD é uma apresentação, não um jogo, o que significa que as implicações do script para todos os sistemas necessários em jogos completos não poderiam surgir. Mais uma vez, a principal preocupação era a otimização da renderização.

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

Nesse caso, a instanciação da GPU foi o método mais útil. Sem isso, haveria 4500 lotes para essa cena. Ao usá-lo, o número poderia ser reduzido para 1832.

Outra conclusão: o número de recursos individuais usados para criar essa cena é realmente muito pequeno. Usando recursos de boa qualidade e colocando-os de maneira inteligente, a equipe criou cenas complexas que não parecem repetitivas e manteve a contagem de lotes baixa com a instanciação da GPU.

Aqui está a cena sem instanciação

console scriptable rendering pipeline

E aqui está com instâncias:

console scriptable rendering pipeline

Use os vários núcleos disponíveis nos consoles

O Xbox One e o PS4 são dispositivos multinúcleo. Para alcançar o melhor desempenho de CPU, devemos tentar manter esses núcleos ocupados o tempo todo.

If you follow Unity news, you’ll know that Unity is currently developing um sistema multithreaded de alto desempenho, 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# Job System and the Burst Compiler.

O novo sistema multithread ainda está no modo experimental inicial. No sistema gráfico da Unity, você pode experimentá-lo via Graphics Jobs (novamente, no modo experimental). Você pode encontrar os controles de Graphics Jobs em Player Settings -> Other Settings.

console Graphics Jobs

O modo Graphics jobs permite otimizar o desempenho em praticamente qualquer ambiente de console, a menos que você precise chamar muitos lotes. Existem dois tipos:

  • Legacy Jobs, disponíveis no PS4, e DirectX 11 para Xbox One
    • Alivia o thread principal, distribuindo o trabalho para outros núcleos. Tenha em mente que, para cenas muito grandes, pode haver um afunilamento no Render Thread, um thread que o Unity usa para endereçar a API gráfica do proprietário da plataforma.
  • Native Jobs, disponível no PS4, e DirectX 12 para Xbox One (em breve)
    • Distribui o máximo de trabalho pelos núcleos disponíveis e é a melhor opção para cenas grandes.
    • Deve ser sempre a melhor opção a partir de 2018.2 (na versão 2018.1 ou anterior, pode haver uma carga de trabalho maior para o thread principal, o que pode diminuir o desempenho).

Use as ferramentas de análise de desempenho do detentor da plataforma

Microsoft and Sony provide ferramentas excelentes 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.

Crie o perfil dos seus efeitos pós-processo

Rob diz que ele criou o perfil dos jogos Unity no PS4, onde, sem o conhecimento dos desenvolvedores, até ⅔ do framerate foi ocupado pelo pós-processamento. Isso geralmente é causado pelo download de recursos de pós-processamento da Asset Store criados principalmente para o PC. Eles parecem funcionar bem no console, mas na verdade mostram características de desempenho insatisfatórias.

So, when ao aplicar esses efeitos, 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.

Evite usar tesselação (a menos que por uma boa razão)

Geralmente não é aconselhável usar tesselação para os gráficos de um jogo de console. Na maioria dos casos, é melhor usar os recursos gráficos adequados em vez de executar uma tesselação de tempo de execução na GPU.

Mas no caso do BOTD, havia uma boa razão para usar tesselação para renderizar a casca da árvore.

console tesselation

O deslocamento tesselado permitiu que a equipe adicionasse geometria aos buracos e detalhes arrojados que projetavam as sombras certas, o que não seria possível com o mapeamento normal.

Como as árvores são objetos "heróis" de longa data no BOTD, essa abordagem foi justificada. Foi tornado possível pela mesma malha para as árvores em LOD 0 e LOD 1. A diferença entre as duas é simplesmente que o deslocamento tesselado foi reduzido de modo que não estava mais em vigor quando o LOD 1 foi atingido.

Visar sempre uma ocupação razoável de frente de onda na GPU

Ok, é fácil dizer, mas a ocupação de frente de onda é de fato um fator importante.

Uma frente de onda pode ser considerada como um pacote de tarefas da GPU. Quando um Drawcall ou um Compute Shader Dispatch é enviado para a GPU, este pacote de tarefas é dividido em várias frentes de onda individuais, que são distribuídas pelos SIMDs em todas as unidades de processamento disponíveis na GPU.

console wave front occupancy

Cada SIMD pode processar um determinado número máximo de frentes de onda em um determinado momento, portanto, há um número total máximo de frentes de onda que podem estar presentes em paralelo na GPU em um determinado momento. O número de frentes de onda usadas é dado pela ocupação da frente de onda. Este é um valor muito útil para entender em que medida o potencial da GPU é explorado para operações paralelas.

Pix e Razor mostram a ocupação da frente de onda em grande detalhe. Os gráficos acima são da Pix para Xbox One. À esquerda, vemos um exemplo de boa ocupação de frente de onda. Abaixo, ao longo da faixa verde, podemos ver algumas frentes de onda de sombreamento de vértice e, acima, em frentes de onda azuis de sombreamento de pixel.

À direita, no entanto, podemos ver um problema de desempenho: o trabalho do shader de vértice dificilmente leva à atividade de sombreamento de pixels aqui. O potencial da GPU não está sendo explorado o suficiente e isso nos leva à próxima dica de otimização.

Como isso acontece? Esse cenário é típico quando se faz um trabalho de sombreamento de vértice que não resulta em pixels.

Utilizar Depth Prepass

Uma análise mais aprofundada com Pix e Razor revelou que houve muito overdraw durante o passe de Gbuffer. Isso tem um impacto particularmente negativo em consoles no que se refere a objetos testados por alfa.

Nos consoles, você não pode aproveitar a rejeição antecipada de profundidade ao emitir instruções de descarte de pixels ou gravar diretamente na profundidade do pixel shader. As frentes de onda de pixel shader são executadas em qualquer caso, mesmo se o trabalho for finalmente descartado.

A solução aqui foi adicionar um Depth Prepass. Isso implica renderizar a cena com antecedência apenas em profundidade, usando shaders muito claros, que podem ser a base de uma rejeição de profundidade mais inteligente na qual você tem seus shaders Gbuffer mais pesados.

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 .

Se você pesquisar em um projeto HDRP para o HD Render PipelineAsset, você encontrará uma grande quantidade de caixas de seleção que controlam tudo o que o HDRP está fazendo.

Para BOTD, o uso do Depth Prepass foi uma ótima vitória da GPU, mas lembre-se que isso adiciona mais lotes à CPU.

Reduza o tamanho de seus alvos de renderização de mapeamento de sombra

Como já mencionado, os mapas de sombra nesta cena são gerados contra uma única luz direcional de projeção de sombra. Quatro divisões de mapa de sombras foram usadas, que inicialmente estavam sendo renderizadas em um mapa de sombra de 4K com profundidade de 32 bits, que é o padrão para projetos de HDRP. Ao renderizar para mapas de sombra, a resolução do mapa de sombra é quase sempre o fator limitante; isto foi confirmado pela análise em Pix e Razor.

Reduzir a resolução do mapa das Sombras era a solução óbvia, embora pudesse afetar a qualidade.

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 fazer o download the project assets.

Finalmente, alterando a resolução do mapa de Sombra, eles também tiveram que alterar algumas configurações de iluminação.

Reduce size of shadow

Nesse ponto, a equipe já havia redesenhado os mapas de sombra e reposicionou a câmera de mapeamento de sombra para tentar obter o melhor aproveitamento da nova resolução reduzida. Então, o que eles fizeram a seguir?

Chame apenas o último mapa de sombra (com menos zoom) dividido uma vez na carga de nível

Como a câmera de mapeamento de sombra não se move muito, isso funcionou para a equipe. A divisão com menos zoom é normalmente usada para renderizar as sombras mais distantes da câmera do Player.

Eles não viram uma queda na qualidade. Acabou sendo uma otimização muito inteligente, pois economizou tempo de framerate da GPU e reduziu os números de lote na CPU.

Após essa série de otimizações, sua fase de criação do mapa de sombra passou de 13ms para pouco menos de 8ms; o passe de iluminação de 4,9ms para 4,4ms e o atmosférico de 6,6ms para 4,2ms.

Neste ponto, a equipe conseguiu concluir a otimização do mapeamento de sombra. Eles estão agora na área onde podem atingir 30 fps no PS4 Pro.

console GPU frame

Utilizar o Contador Assíncrono

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.

A fase somente de profundidade, que é feita com mapeamento de sombra, é tradicionalmente o ponto em que o potencial da GPU não é totalmente explorado. O Async Compute permite executar o trabalho do compute shader em paralelo com a fila de gráficos, usando recursos que a fila gráfica está subutilizando.

BOTD usa o Async Compute para a coleção de lista de luzes lado a lado, que faz parte da iluminação diferida, tudo feito principalmente com compute shaders no no console em HDR . Além disso, BOTD usa isso para os cálculos do SSAO. Ambos se sobrepõem à renderização do mapa de sombras para preencher as lacunas na utilização da frente de onda.

For a run-through of some conceptual code where Async Compute is employed, tune into a sessão do Rob na Unite at 35:30.

Mais recursos

Queremos saber! Você gostou deste conteúdo?

Sim, continue. Bem. Poderia ser melhor
Eu entendi

Usamos cookies para garantir a melhor experiência no nosso site. Clique aqui para obter mais informações.