Quick answer: Confirm SwappyGL_init (or SwappyVk_init) returned true. Replace eglSwapBuffers with SwappyGL_swap. Set target frame rate via SwappyGL_setSwapIntervalNS.

A mobile game stutters when reaching demanding scenes. Frame Pacing library is in the build but stutter persists. Engine still uses eglSwapBuffers directly — library never gets called.

Verify Init

bool initOk = SwappyGL_init(env, activity);
__android_log_print(ANDROID_LOG_INFO, "Game", "Swappy init: %d", initOk);

Run, check logcat. False = device unsupported or activity context missing. True = library ready.

Replace Swap Call

// Before:
eglSwapBuffers(display, surface);

// After:
SwappyGL_swap(display, surface);

Single function replacement. Swappy handles pacing internally; falls back to eglSwapBuffers on init failure.

Set Target Frame Rate

SwappyGL_setSwapIntervalNS(16666666);   // 60fps
SwappyGL_setAutoSwapInterval(true);   // auto adapt

60fps target = 16.66ms interval. AutoSwapInterval lets Swappy drop to 30fps if 60 not sustainable; better than judder.

Disable Engine VSync

If using Unity/Unreal, the engine’s vsync setting may conflict. Disable engine-level vsync; let Swappy handle:

Vulkan Variant

For Vulkan: use SwappyVk_initAndGetRefreshCycleDuration + SwappyVk_queuePresent instead of vkQueuePresentKHR.

Verifying

logcat -s Swappy: per-frame pacing metrics. Stable 60fps in stat. Visual: smoother feel, no judder during scene transitions.

“Library needs to actually be in the swap call path. Replace eglSwapBuffers and confirm via logcat.”

For 120Hz devices (Pixel 7+, Galaxy S22+), set interval 8333333 (8.33ms) and watch thermal — sustained 120fps drains battery fast.