A biblioteca Android Frame Pacing, também conhecida como Swappy, faz parte do Android Game SDK. Ela ajuda jogos OpenGL e Vulkan a ter uma renderização uniforme e a corrigir o ritmo de frame 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
- Detecção de envios de frames atrasados
- Continuação da exibição do 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 subjacente, levando a tempos de exibição inconsistentes. Por exemplo, quando um jogo executado 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 excessivamente complexas agravam ainda mais esse problema porque causam frames perdidos.
A biblioteca Frame Pacing realiza estas tarefas:
- Compensa a renderização lenta devido a frames curtos de jogos.
- Adiciona carimbos de data/hora de apresentação para que os frames sejam apresentados no horário, não antes.
- Usa extensões de carimbo de data/hora de apresentação
EGL_ANDROID_presentation_timeeVK_GOOGLE_display_timing.
- Usa limites de sincronização para frames longos que levam a 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 limites de sincronização (
EGL_KHR_fence_synceVkFence).
- Escolhe uma taxa de atualização para oferecer flexibilidade e uma apresentação uniforme, se o dispositivo for compatível com várias taxas de atualização.
- Fornece estatísticas para depuração e caracterização de perfil usando estatísticas de frame.
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 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 do jogo. As informações de QPS são armazenadas no
GameManagerService com outras informações de intervenção, como o fator de redução de resolução,
em um <PACKAGE_NAME, Interventions> mapeamento para cada perfil de usuário.
As informações de QPS 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 de QPS de um aplicativo, desde que a frame rate seja um divisor da taxa de atualização da tela. No caso de um 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 frame rate do aplicativo. Se a frame rate não estiver em fase com o VSync, o SurfaceFlinger vai manter o frame até que a frame rate 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 par <UID, Frame Rate>
mapeamento para definir uma nova prioridade de limitação de frame rate. O UID é exclusivo entre usuários e jogos, para que cada usuário em um único dispositivo possa ter configurações diferentes de frame rate no mesmo jogo. Para limitar a frame rate de um jogo, o GameManagerService chama o SurfaceFlinger para substituir a frame rate 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 QPS fixando buffers de acordo.
Para entender melhor a limitação de QPS, consulte Limitação de QPS.