Frame Pacing

A biblioteca Android Frame Pacing, também conhecida como Swappy, faz parte do SDK para jogos do Android. Ela ajuda jogos OpenGL e Vulkan a ter uma renderização uniforme e a corrigir o ritmo de frames no Android.

O ritmo de frame é a sincronização da lógica e do loop de renderização de um jogo com o subsistema e o hardware de exibição de um SO. O subsistema de exibição do Android foi projetado para evitar determinados artefatos visuais, como o tearing. O subsistema de exibição evita o tearing fazendo o seguinte:

  • Armazenamento em buffer de frames anteriores internamente
  • Detectar envios de frames atrasados
  • Continuar mostrando o frame atual quando um frame atrasado é detectado

Tempos de exibição de frames inconsistentes são causados por um loop de renderização de um jogo executado a uma taxa diferente daquela compatível com o hardware de exibição nativo. Os problemas surgem quando o loop de renderização de um jogo é executado muito lentamente para o hardware de exibição, resultando em tempos de exibição inconsistentes. Por exemplo, quando um jogo em execução a 30 fps tenta renderizar um dispositivo que tenha compatibilidade nativa com 60 fps, o loop de renderização do jogo faz com que um frame repetido permaneça na tela por mais 16 ms. Esse tipo de desconexão cria inconsistências substanciais nos tempos de frame como 33 ms, 16 ms e 49 ms. Cenas extremamente complexas agravam esse problema porque causam a perda de frames.

A biblioteca Frame Pacing executa estas tarefas:

  • Compensa a renderização lenta causada por frames curtos de jogos.
  • Usa barreiras de sincronização para frames longos que causam renderização lenta e latência.
    • Injeta esperas no app. Isso permite que o pipeline de exibição seja atualizado, em vez de permitir que a pressão de retorno se acumule.
    • Usa barreiras de sincronização (EGL_KHR_fence_sync e VkFence).
  • Escolhe uma taxa de atualização para oferecer flexibilidade e uma apresentação suave, se o dispositivo for compatível com várias taxas de atualização.
  • Fornece estatísticas para depuração e criação de perfil usando estatísticas de frames.

Para saber como configurar a biblioteca para operar em diferentes modos de acordo com suas necessidades, consulte Modos de operação compatíveis.

Para implementar usando o renderizador OpenGL ou Vulkan, consulte:

Para saber mais, consulte a biblioteca Frame Pacing.

Intervenção de limitação de quadros por segundo

A intervenção de limitação de quadros por segundo (QPS) permite que os jogos tenham um ritmo adequado de QPS com apenas mudanças na plataforma e sem exigir nenhuma ação dos desenvolvedores.

A implementação da intervenção de limitação de QPS usa os seguintes componentes.

GameManagerService

O componente GameManagerService mantém todas as informações por usuário e por jogo do modo de jogo e da intervenção no jogo. As informações de FPS são armazenadas no GameManagerService com outras informações de intervenção, como o fator de redução da resolução, em um mapeamento <PACKAGE_NAME, Interventions> para cada perfil de usuário. As informações de FPS são acessadas quando o modo de jogo é alterado ou a intervenção é atualizada. Um UID é exclusivo para cada PACKAGE_NAME e usuário, e pode ser traduzido em um par <UID, Frame Rate> para enviar ao SurfaceFlinger.

SurfaceFlinger

O componente SurfaceFlinger já oferece suporte à limitação do FPS de um aplicativo, desde que a taxa de frames seja um divisor da taxa de atualização da tela. Em caso de VSync, o SurfaceFlinger verifica a validade do VSync para o aplicativo limitado, verificando se o carimbo de data/hora do VSync está em fase com a taxa de frames do aplicativo. Se a taxa de frames não estiver em fase com o VSync, o SurfaceFlinger vai manter o frame até que a taxa de frames e o VSync estejam em fase.

A figura a seguir descreve a interação entre o GameManagerService e o SurfaceFlinger:

Interação entre o GameManagerService e o SurfaceFlinger

Figura 1. Interação entre o GameServiceManager e o SurfaceFlinger.

O SurfaceFinger mantém um mapeamento de par <UID, Frame Rate> para definir uma nova prioridade de limitação da taxa de frames. O UID é exclusivo entre usuários e jogos, para que cada usuário em um único dispositivo possa ter configurações diferentes de taxa de frames no mesmo jogo. Para limitar a taxa de frames de um jogo, o GameServiceManager chama o SurfaceFlinger para substituir a taxa de frames de um UID. Com esse mecanismo, o SurfaceFlinger atualiza o mapeamento sempre que o modo de jogo é alterado ou a intervenção é atualizada. O SurfaceFlinger processa a mudança de FPS ao fixar buffers de acordo.

Para entender melhor a limitação de QPS, consulte Limitação de QPS.