Otimização de renderização para dispositivos móveis, parte 2. As principais famílias de GPUs móveis modernas

Saudações, queridos amantes e profissionais, programadores gráficos! Vamos começar a segunda parte de nossa série de artigos sobre otimização de renderização para celular. Nesta parte, consideraremos as principais famílias de GPUs apresentadas pelos jogadores no celular.


Para começar, considere vários critérios pelos quais as GPUs móveis podem ser classificadas.

Núcleos de shader unificados ou especializados


Na era das primeiras placas de vídeo móveis, antes da disseminação de efeitos complexos, havia um ponto de vista de que, para shaders de fragmentos, o suporte a cálculos com precisão reduzida é suficiente. De fato, em um modo de exibição típico, 8 ou menos bits são usados ​​para cada canal de cores. Essa visão levou ao uso de núcleos de shader especializados. Para os vértices, usamos kernels otimizados para transformações de matriz com maior precisão FP24 / FP32 ( highp ). Para pixels, núcleos que funcionam mais eficientemente com precisão reduzida FP16 ( mediump ). Com este highpeles não eram suportados. À primeira vista, essa especialização nos permite obter uma distribuição mais racional dos transistores no chip. No entanto, na prática, isso leva a dificuldades no desenvolvimento de efeitos complexos, bem como no uso de texturas de alta resolução. Além disso, a especialização principal pode levar a um gargalo de vértice / fragmento . Este termo refere-se à situação em que, devido à carga assimétrica nos núcleos de vértice e pixel, alguns núcleos estavam "inativos". 


Portanto, arquiteturas modernas usam núcleos unificados. Esses kernels podem assumir vértices, pixels e outras tarefas computacionais, dependendo da carga.


Conjunto de instruções vetorial (SIMD) ou escalar


No espírito do desejo de economizar nos transistores descritos acima, especializado em núcleos, ocorreu o design de um conjunto de instruções de shader. As transformações mais comuns para gráficos tridimensionais operam com 4 vetores de componentes. Portanto, as primeiras GPUs trabalhavam especificamente com esses operandos. Se o código do sombreador continha operações escalares heterogêneas que não podiam ser empacotadas em operações vetoriais pelo otimizador, parte da capacidade de computação não era usada. Este fenômeno pode ser ilustrado da seguinte forma:


Há um sombreador que implementa a operação comum de adição de multiplicação: multiplique 2 operandos e adicione o terceiro. Ao compilar em uma arquitetura vetorial condicional (Vector ISA = Arquitetura de conjunto de instruções vetoriais), obtemos uma instrução vetorial vMADD , que é executada por 1 relógio. Na arquitetura escalar condicional, obtemos 4 instruções escalares que, graças a um pipeline aprimorado, também são executadas em 1 ciclo de clock. Agora considere um sombreador sofisticado que executa 2 operações, mas em 2 operandos componentes.


No caso da arquitetura vetorial, já temos 2 instruções que requerem 2 ciclos de clock para serem executadas. No entanto, nenhuma ação é executada nos componentes .zw e a capacidade de processamento fica inativa. No caso da arquitetura escalar, essas mesmas operações podem ser empacotadas em 4 sMADDs escalares que são executados no mesmo ciclo de 1 relógio. Assim, na arquitetura escalar, devido à melhoria do pipeline, é alcançada uma maior densidade de cálculos. No entanto, como será mostrado abaixo, o vetor ISA ainda é relevante. Portanto, faz sentido aplicar técnicas de vetorização para código de sombreador. Eles permitem obter maior desempenho em placas de vídeo com o vetor ISA . Ao mesmo tempo, como regra, isso não prejudica o desempenho em escalares mais modernos.O ISA .

Com base nas características acima, consideraremos as famílias de GPUs móveis que são comuns em nosso tempo. Vamos começar com a família mais comum. Muitas pessoas sabem que estamos falando sobre placas gráficas do Mali da empresa britânica ARM . A ARM não está diretamente envolvida na produção de chips, oferecendo propriedade intelectual. Como outras placas de vídeo para celular, o Mali faz parte do System on Chip (SoC) , ou seja, trabalha com compartilhada memória para a CPU e GPU e ônibus. 

Mali utgard


Em 2008, nasceram os primeiros representantes da arquitetura do Mali Utgard , relevantes até os dias atuais. Essas placas de vídeo são nomeadas de acordo com o esquema Mali-4 xx MP n , em que xx é o número do modelo en é o número de núcleos de fragmento. Na especialidade do Mali Utgard shader core, e todos os modelos vêm com um vértice apenas 1 núcleo.

Outras características da arquitetura Mali Utgard:

  • OpenGL ES 2.0 
  • Falta de suporte highp em kernels fragmentados
  • Conjunto de instruções vetoriais (faz sentido vetorizar cálculos)

Apesar da especificação do OpenGL ES , os drivers da placa de vídeo Mali Utgard compilam com êxito os shaders de fragmentos que usam alta precisão (por exemplo, a precisão é definida por padrão usando a precisão highp float ). Mas a precisão do mediump é realmente usada . Portanto, é aconselhável testar adicionalmente todos os shaders para jogos para celular nessas placas de vídeo. De acordo com dados coletados pela Unity , no final de 2019, Mali Utgard trabalhou em dispositivos para cerca de 10% dos jogadores. E se você definir os filtros apropriados no market.yandex.ru , poderá ver em 2019 mais de 10 novos telefones com placas de vídeo dessa arquitetura.


Se você estiver pronto para abandonar esse público, basta definir o requisito para o suporte ao OpenGL ES 3.0 no AndroidManifest.xml:

<uses-feature android:glEsVersion="0x00030000" android:required="true"⁄>

Além do Mali Utgard , atualmente não existem GPUs móveis comuns sem suporte ao OpenGL ES 3.0.

Destaca-se o uso de texturas de alta resolução no Mali Utgard . Dez bits da mantissa com precisão média não são suficientes para texturas de alta qualidade com uma resolução de textura superior a 1024 em um lado. No entanto, apesar de oferecer suporte apenas à precisão de médios médios nos núcleos de fragmentos do Mali Utgard , é possível obter a precisão das coordenadas de textura fp24 ao usar variações diretamente.

// vertex shader
varying highp vec2 v_texc;
void main()
{
    v_texc = …;
}

//  fragment shader
...
varying highp vec2 v_texc;
void main()
{
    gl_FragColor = texture2D(u_sampler, v_texc); //  v_texc 
                                                 //  
}

Como um bônus em algumas arquiteturas, essa abordagem permite pré - buscar o conteúdo da textura antes de executar um sombreador de fragmento , o que minimiza as paradas enquanto aguarda os resultados da amostragem de textura.

Mali midgard


O Mali Utgard foi substituído pela arquitetura do Mali Midgard . Existem várias gerações dessa arquitetura com os nomes das espécies Mali-6xx , Mali-7xx e Mali-8xx . Apesar da idade de 8 anos, o Mali Midgard pode ser chamado de arquitetura moderna que fornece suporte para a maioria dos novos recursos:

  • grãos de shader unificados
  • OpenGL ES 3.2 (sombreadores de computação e geometria, mosaico ...)

No entanto, o Mali Midgard mantém o vetor ISA . Dado o amplo uso do Mali Midgard (cerca de 25% da nossa audiência), a vetorização da computação se torna apropriada.

Outro recurso do Mali Midgard é a tecnologia Forward Pixel Kill . Cada pixel é calculado em um fluxo separado do núcleo do fragmento. Se durante a execução do fluxo se souber que o pixel resultante será bloqueado por um pixel opaco de outro primitivo, o fluxo será encerrado prematuramente e os recursos liberados serão utilizados para outros cálculos.

Mali bifrost


Ao lado de Midgard, a arquitetura Bifrost se destaca por sua transição para o ISA escalar . Comparado à arquitetura anterior, o número máximo de núcleos foi aumentado (de 16 para 32), e uma interface aprimorada com uma CPU é suportada, o que permite acesso coerente à memória compartilhada: alterações no conteúdo da memória da CPU / GPU tornam-se imediatamente "visíveis" entre si, apesar dos caches, que permite simplificar a sincronização.

De não oficial


Muitas tentativas foram feitas para fazer engenharia reversa das placas de vídeo do Mali para criar drivers de código aberto para Linux . Os trabalhos das pessoas dedicadas que tentam fazer isso nos permitem dar uma olhada nos recursos não documentados das placas de vídeo do Mali . Portanto, no projeto PanFrost , um desmontador para o Mali Midgard / Bifrost , com o qual você pode se familiarizar com um conjunto de instruções de sombreador (não há informações oficiais abertas sobre esse tópico).


Adreno


A segunda família mais comum de GPUs móveis é o Adreno . Esta placa de vídeo é instalada no SoC , conhecido sob a marca Snapdragon , da empresa americana Qualcomm . O Snapdragon é instalado nos smartphones de última geração da Samsung , Sony e outros.As

placas de vídeo Adreno atuais são as famílias das séries 3xx - 6xx. Todas essas séries combinam os seguintes recursos:

  • grãos de shader unificados
  • Pseudo TBR (tamanhos grandes de blocos localizados em uma memória GPU dedicada tradicional)
  • Troca automática no modo Imediato Rendering, dependendo da natureza da cena ( FlexRender )
  • Conjunto de instruções escalares

A partir do Adreno 4xx , é introduzido o suporte ao OpenGL ES 3.1 e com o Adreno 5xx - Vulkan e o OpenGL ES 3.2 .

Renderização baseada em mosaico Adreno


As placas de vídeo Adreno têm uma GPU "tradicional" chamada GMEM . Aplicam-se volumes de 128kb a 1536kb. Isso permite que você use um tamanho de bloco maior em comparação com arquiteturas de outros desenvolvedores de GPUs móveis. No Adreno, o tamanho dos ladrilhos é dinâmico e depende do formato de cor usado, do buffer de profundidade e do estêncil. Ao trabalhar no modo imediato, a renderização ocorre na memória do sistema.Há uma extensão GL ES que permite especificar o modo preferido: QCOM_binning_control . No entanto, as recomendações mais recentes da Qualcomm sugerem confiar inteiramente nos drivers da GPU, que determinam o modo mais preferido para o buffer de comando gerado pelo aplicativo. 

Ao trabalhar no modo TBR Adreno faz 2 passes de vértice:

  1. Binning pass - distribuição de primitivas por bin ( caixas , sinônimo de blocos)
  2. Passagem completa do vértice para renderizar apenas as primitivas que se enquadram na Lixeira atual

Durante o passe de Binning, o Adreno calcula apenas as posições dos vértices. Outros atributos não são calculados e o código desnecessário é removido pelo otimizador. Na documentação oficial (9.2 Otimizar o processamento de vértices), há uma recomendação para armazenar as informações de vértices necessárias para calcular as posições separadamente do restante dos dados. Isso torna o cache de dados de vértices mais eficiente.

Freedreno


Diferentemente da ARM e da Imagination Technologies, a Qualcomm reluta em compartilhar os detalhes da estrutura interna de suas GPUs. No entanto, graças aos esforços do engenheiro reverso Rob Clark, muito pode ser aprendido com o projeto Freedreno , o driver de código aberto Adreno para Linux.

Rob Clark por Freedreno

PowerVR por Imagination Technologies


A Imagination Technologies é uma empresa britânica famosa por desenvolver GPUs para produtos da Apple. A empresa desempenhou esse papel até o advento do iPhone 8 / X, que usa o desenvolvimento interno da Apple. Embora as recomendações sobre otimizações para esses chips, bem como sobre reivindicações de patentes contra a Apple da Imagination, que permaneceram inalteradas, sugiram que a Apple continuou a desenvolver a arquitetura PowerVR, um desenvolvimento original da Imagination. No início de 2020, a Apple voltou às práticas de licenciamento com a Imagination Technologies. Além dos dispositivos com iOS / iPadOS, as placas de vídeo PowerVR são instaladas em um grande número de smartphones e tablets Android.


Considere a família de placas gráficas PowerVR que ainda podem ser encontradas entre os usuários.

PowerVR SGX


As primeiras placas gráficas PowerVR SGX apareceram em 2009. Existem várias gerações dessa arquitetura: Series5, Series5XT e Series5XE. A Apple usou essas GPUs até o iPAD 4 / iPhone 5 / iPOD Touch 5. Os seguintes recursos SGX podem ser citados:

  • grãos de shader unificados
  • OpenGL ES 2.0
  • conjunto de instruções do vetor
  • suporte para precisão lowp de 10 bits em shaders
  • baixo desempenho de leituras de textura dependentes

Vamos nos debruçar sobre alguns deles com mais detalhes. 

Precisão Lowp


O PowerVR SGX são as únicas GPUs móveis atualizadas com suporte de hardware
lowp . Os modelos PowerVR mais recentes, bem como todas as GPUs modernas de outros fornecedores, na verdade usam precisão de médios . O uso de
lowp no PowerVR SXG permite alcançar uma densidade de computação mais alta (mais operações por ciclo). Ao mesmo tempo, a operação swizzle (permutação dos componentes vetoriais) para lowp , diferentemente de outra precisão, não é livre. Esse recurso, assim como a faixa estreita de valores que lowp fornece ([-2,2]), limita seu escopo. Ao mesmo tempo, o lowp mal definidoresultando em artefatos na família SGX não serão vistos em todas as outras placas gráficas em que a precisão média será realmente usada . Por esse motivo, considere recusar-se a usar lowp em shaders.

Leituras de textura dependente


Como você sabe, as operações de amostragem de textura são as mais lentas devido à necessidade de esperar pelos resultados da leitura da memória. No caso do SoC móvel, estamos falando de memória compartilhada do sistema com uma CPU. Para reduzir o número de acessos à memória lenta, são usados ​​caches de textura. Para evitar o tempo de inatividade no início da rasterização usando uma textura, faz sentido armazenar em cache as áreas usadas com antecedência. Se o shader de fragmento usar a coordenada de textura passada pelo shader de vértice sem alterações, a seção de textura necessária para o armazenamento em cache poderá ser determinada antes da execução do shader de fragmento. Se o sombreador do fragmento alterar a coordenada da textura ou calculá-la usando dados de outra textura, isso nem sempre é possível. Como resultado, a execução do sombreador de fragmento pode ficar mais lenta.As placas de vídeo PowerVR SGX são particularmente dolorosas nesse cenário. Além disso, mesmo o uso de uma permutação dos componentes da coordenada de textura (swizzle) leva atextura dependente lida . Aqui está um programa de shader de exemplo sem a leitura de textura dependente .

programa de vértice

attribute highp vec2 a_texc;
varying highp vec2 v_texc;

void main()
{
	gl_Position = …
	v_texc = a_texc;
}


programa de fragmento

precision mediump float;
uniform sampler u_sampler;
varying highp vec2 v_texc;

void main()
{
	gl_FragColor = texture2D( u_sampler, v_texc ); //  dependent texture read
}

Nesse caso:

programa de fragmento

precision mediump float;
uniform sampler u_sampler;
varying highp vec2 v_texc;

void main()
{
	gl_FragColor = texture2D( u_sampler, v_texc.yx ); // dependent texture read!
}

PowerVR Rogue


As placas de vídeo PowerVR foram desenvolvidas na arquitetura Rogue e existem várias gerações dessa arquitetura: da Série6 à Série9. Todos os PowerVR Rogue possuem esses recursos:

  • grãos de shader unificados
  • arquitetura de instruções escalares
  • suporte para OpenGL ES 3.0+ (até 3.2, bem como a API Vulkan para novas réguas) 

PowerVR TBDR


Como todas as GPUs móveis comuns, o PowerVR usa um pipeline de blocos. Mas, diferentemente dos concorrentes, o Imagination foi além e implementou a rasterização adiada de primitivas, permitindo pular o sombreamento de pixels invisíveis, independentemente da ordem de renderização. Essa abordagem é chamada renderização adiada com base em bloco e o processo de eliminação de pixels invisíveis é chamado de remoção de superfície oculta (HSR).


Remoção de superfícies ocultas

Recomenda-se desenhar uma geometria opaca para ficar transparente e não usar o Z Prepass, que no caso das placas de vídeo PowerVR na maioria dos cenários levará a trabalhos desnecessários. No entanto, vários pixels transparentes consecutivos que se sobrepõem são completamente sombreados para obter a cor correta, levando em consideração a mistura. O último pixel transparente pode ser descartado se for seguido por um pixel opaco. 

Tecnologias de imaginação de abertura


Os criadores do PowerVR forneceram acesso aberto a mais documentação do que outros desenvolvedores de GPU. A arquitetura do pipeline gráfico é descrita em detalhes, bem como um conjunto de instruções para a arquitetura Rogue . Existe uma ferramenta conveniente PVRShaderEditor , que permite que você receba instantaneamente informações de perfil no shader, bem como sua lista desmontada do Rogue.


Apesar da presença limitada de placas de vídeo PowerVR no ambiente de dispositivos baseados no Android, faz sentido estudar sua arquitetura para a programação competente de gráficos para iOS.

GPUs móveis de modo imediato


Examinamos as famílias mais comuns de placas de vídeo móveis. Todas essas famílias usavam arquitetura de renderização de blocos. No entanto, existem placas de vídeo móveis que usam a abordagem tradicional do modo imediato . Aqui estão alguns deles:

  • nVIdia (Tegra SoC)
  • Toda a família Intel, exceto a recente geração 11
  • Vivante GCxxxx (+ Arcturus GC8000)

Um recurso das placas de vídeo móveis que operam no modo imediato é a cara operação de limpeza da FBO. Lembre-se de que na arquitetura do bloco, a limpeza em tela cheia acelera a renderização, permitindo que o driver não adicione a operação Carregar do conteúdo antigo à memória do bloco. Nas GPUs móveis de modo imediato, a limpeza em tela cheia é uma operação demorada que permite, entre outras coisas, que essas GPUs “calculem”. Se a adição de limpeza não acelerar, mas diminuir a renderização, provavelmente estaremos trabalhando com a GPU no modo imediato . Bem, é claro, não vamos esquecer de mencionar que nas GPUs de modo imediato, alterar um alvo é um procedimento "condicionalmente livre".

Distribuição de diferentes famílias de GPUs móveis entre nossos players


Aqui estão as estatísticas de GPUs móveis coletadas de nossos jogadores no final de 2019:


Abaixo, abrimos o segmento "Outros"


Com base nesses dados, analisamos a distribuição da GPU em termos de seus principais recursos.


As ALUs vetoriais (unidade lógica aritmética) tornam-se obsoletas e substituídas por escalares. Hoje, a maior parte das GPUs móveis com um conjunto de instruções vetoriais é o Mali Midgard , que pode ser considerado com desempenho médio. Porque a vetorização, por via de regra, não diminui a execução nas ALUs escalares; vale a pena considerar a vetorização como uma técnica real para otimizar shaders para dispositivos móveis. 

Os kernels shader especializados foram descontinuados e substituídos pelos unificados. O gargalo de vértice na malha esquelética não é mais assustador. Núcleos especializados são usados ​​apenas na família Mali-4xx (Utgard) . Lembre-se de que essas GPUs oferecem suporte apenas ao OpenGL ES 2.0 . Nosso público-alvo possui cerca de 3,5% deles.

Por fim, a grande maioria das GPUs móveis usa a abordagem de blocos. O Modo Imediato ficou marginalizado e está sendo espremido rapidamente junto com as placas de vídeo que o utilizam. A participação de GPUs de modo imediato em nossos jogadores é de cerca de 0,7%.

Links Úteis:


Obrigado pela atenção! No próximo artigo da série, consideraremos técnicas para otimizar shaders para dispositivos móveis.

All Articles