Swappy라고도 하는 Android 프레임 페이싱 라이브러리는 Android 게임 SDK의 일부입니다. 이 라이브러리는 OpenGL 및 Vulkan 게임이 Android에서 원활한 렌더링 및 올바른 프레임 페이싱을 구현하는 데 도움이 됩니다.
프레임 페이싱은 게임의 로직 및 렌더링 루프를 OS의 디스플레이 하위 시스템 및 기본 디스플레이 하드웨어와 동기화하는 것입니다. Android 디스플레이 하위 시스템은 테어링과 같은 특정 시각적 아티팩트를 방지하도록 설계되었습니다. 디스플레이 하위 시스템은 다음을 실행하여 테어링을 방지합니다.
- 내부적으로 이전 프레임 버퍼링
- 지연된 프레임 제출 감지
- 지연된 프레임이 감지될 때 현재 프레임을 계속 표시
일관되지 않은 프레임 표시 시간은 게임의 렌더링 루프가 네이티브 디스플레이 하드웨어에서 지원하는 것과 다른 속도로 실행되어 발생합니다. 게임의 렌더링 루프가 기본 디스플레이 하드웨어에서 너무 느리게 실행될 때 발생하는 문제로 표시 시간이 일관되지 않게 됩니다. 예를 들어 30fps로 실행되는 게임이 기본적으로 60fps를 지원하는 기기에서 렌더링하려고 하면 게임의 렌더링 루프가 반복되는 프레임을 화면에 16ms 동안 추가로 유지되게 합니다. 이러한 유형의 연결 해제로 인해 33ms, 16ms, 49ms 등과 같은 프레임 시간에 상당한 불일치가 발생합니다. 지나치게 복잡한 장면은 이 문제를 더 악화시킵니다. 이러한 장면으로 인해 프레임이 누락되기 때문입니다.
프레임 페이싱 라이브러리는 다음 작업을 실행합니다.
- 짧은 게임 프레임으로 인한 끊김 현상을 보정합니다.
- 프레임이 일찍 표시되지 않고 제때 표시되도록 프레젠테이션 타임스탬프를 추가합니다.
- 프레젠테이션 타임스탬프 확장 프로그램
EGL_ANDROID_presentation_time
및VK_GOOGLE_display_timing
을 사용합니다.
- 끊김 현상과 지연 시간을 유발하는 긴 프레임에 동기화 펜스를 사용합니다.
- 앱에 대기를 삽입합니다. 이렇게 하면 백 프레셔가 쌓이는 대신 디스플레이 파이프라인이 따라잡을 수 있습니다.
- 동기화 펜스(
EGL_KHR_fence_sync
및VkFence
)를 사용합니다.
- 기기에서 여러 화면 재생 빈도를 지원하면 화면 재생 빈도를 선택하여 유연성과 원활한 프레젠테이션을 제공합니다.
- 프레임 통계를 사용하여 디버깅 및 프로파일링 통계를 제공합니다.
필요에 따라 다양한 모드에서 작동하도록 라이브러리를 구성하는 방법은 지원되는 작동 모드를 참고하세요.
OpenGL 렌더기나 Vulkan 렌더기를 사용하여 구현하려면 다음을 참고하세요.
자세한 내용은 올바른 프레임 페이싱 알아보기를 참고하세요.
초당 프레임 수 제한 개입
초당 프레임 수(FPS) 제한 개입을 사용하면 개발자가 아무런 조치를 취하지 않아도 플랫폼 측 변경사항만 사용하여 게임이 적절한 FPS로 진행될 수 있습니다.
FPS 제한 개입 구현에는 다음 구성요소가 사용됩니다.
GameManagerService
GameManagerService 구성요소는 게임 모드와 게임 개입에 관한 모든 사용자별 및 게임별 정보를 유지합니다. FPS 정보는 각 사용자 프로필의 <PACKAGE_NAME, Interventions>
매핑에 있는 다른 개입 정보(예: 해상도 축소 계수)와 함께 GameManagerService에 저장됩니다.
게임 모드가 변경되거나 개입이 업데이트될 때 FPS 정보에 액세스합니다. UID
는 각 PACKAGE_NAME
및 사용자에 고유하며 SurfaceFlinger로 전송하기 위해 <UID, Frame Rate>
쌍으로 추가로 변환될 수 있습니다.
SurfaceFlinger
SurfaceFlinger 구성요소는 프레임 속도가 화면 재생 빈도의 제수인 한 애플리케이션의 FPS 제한을 이미 지원합니다. vsync가 발생하는 경우 SurfaceFlinger는 vsync 타임스탬프가 애플리케이션의 프레임 속도와 일치하는지 확인하여 제한된 애플리케이션의 vsync 유효성을 검사합니다. 프레임 속도가 vsync와 일치하지 않는 경우 SurfaceFlinger는 프레임 속도와 vsync가 일치할 때까지 프레임을 유지합니다.
다음 그림은 GameManagerService와 SurfaceFlinger 간의 상호작용을 설명합니다.
![GameManagerService와 SurfaceFlinger 간의 상호작용](https://source.android.google.cn/static/docs/core/graphics/images/fps-throttling-flow.png?authuser=4&hl=ko)
그림 1. GameServiceManager와 SurfaceFlinger 간의 상호작용
SurfaceFinger는 <UID, Frame Rate>
쌍 매핑을 유지하여 새 프레임 속도 제한 우선순위를 설정합니다. UID
는 사용자와 게임 간에 고유하므로 단일 기기의 각 사용자는 동일한 게임에서 프레임 속도 설정을 다르게 할 수 있습니다. 게임의 프레임 속도를 제한하기 위해 GameServiceManager는 SurfaceFlinger를 호출하여 UID의 프레임 속도를 재정의합니다. 이 메커니즘을 통해 SurfaceFlinger는 게임 모드가 변경되거나 개입이 업데이트될 때마다 매핑을 업데이트합니다. SurfaceFlinger는 버퍼를 적절하게 래칭하여 FPS 변경을 처리합니다.
FPS 제한에 대한 자세한 내용은 FPS 제한 소개를 참고하세요.