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.
- Adiciona carimbos de data/hora de apresentação para que os frames sejam apresentados no momento certo, e não antes.
- Usa extensões de carimbo de data/hora da apresentação
EGL_ANDROID_presentation_time
eVK_GOOGLE_display_timing
.
- 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
eVkFence
).
- 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:
- Integrar a Android Frame Pacing ao renderizador OpenGL
- Integrar o Android Frame Pacing ao renderizador Vulkan
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:

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.