VSync (Vertical Synchronization) — technologia synchronizująca wyświetlanie każdej nowej klatki GPU z częstotliwością odświeżania ekranu, eliminując rozrywanie obrazu. Według Apple Metal Documentation, synchronizacja z VBlank jest obowiązkowa dla płynnego renderowania na urządzeniach mobilnych. Screen tearing występuje, gdy klatka jest aktualizowana podczas pionowego przemiatania, a VSync zapobiega temu mieszaniu.
Najważniejsze
VSync (Vertical Synchronization) — mechanizm sprzętowo-programowy, który zmusza GPU do oczekiwania na sygnał pionowego wygaszania (VBlank) przed wyświetleniem nowej klatki. Bez VSync GPU może wysyłać klatki w dowolnym momencie, nawet gdy ekran jest w trakcie renderowania bieżącej klatki, co prowadzi do rozrywania obrazu wzdłuż poziomej linii.
W urządzeniach mobilnych VSync jest zaimplementowany na poziomie sterownika graficznego i systemu operacyjnego. iOS używa synchronizacji VBlank przez Metal, Android — przez SurfaceFlinger i BufferQueue. Przy włączonej synchronizacji pionowej FPS aplikacji nie może przekroczyć częstotliwości odświeżania ekranu — 60, 90 lub 120 Hz w zależności od modelu urządzenia.
Termin synchronizacja pionowa pochodzi od mechanizmu działania monitorów CRT, gdzie wiązka elektronów rysowała obraz linia po linii od góry do dołu. Po zakończeniu klatki wiązka wracała w lewy górny róg — ten moment nazywano pionowym wygaszaniem. Nowoczesne wyświetlacze LCD i OLED zachowały ten termin, mimo że fizycznie działają inaczej.
GPU renderuje klatki w back buffer, a ekran czyta z front buffer. VSync gwarantuje, że przełączanie buforów (swap) następuje tylko w momencie VBlank — gdy ekran zakończył wyświetlanie bieżącej klatki i jest gotowy na następną. Ten mechanizm nazywa się podwójnym buforowaniem z synchronizacją przez VBlank.
Podwójne buforowanie wykorzystuje dwa bufory: front buffer, wyświetlany na ekranie, i back buffer, do którego GPU pisze bieżącą klatkę. Gdy klatka jest gotowa, bufory zamieniają się miejscami. Przy włączonym VSync to przełączenie jest opóźniane do najbliższego VBlank. GPU pozostaje bezczynne, jeśli klatka jest gotowa przed VBlank, co obniża wydajność, ale eliminuje tearing.
// OpenGL — włączanie VSync przez WGL_EXT_swap_control
HDC hdc = wglGetCurrentDC();
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT =
reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(
wglGetProcAddress("wglSwapIntervalEXT"));
wglSwapIntervalEXT(1); // 1 = VSync włączony, 0 = wyłączony
VBlank — krótki odstęp czasu między ostatnią linią bieżącej klatki a pierwszą linią następnej. W tym momencie ekran nie aktualizuje pikseli, a przełączenie buforów odbywa się bez artefaktów. Długość VBlank zależy od częstotliwości odświeżania: przy 60 Hz na ekranie 1080p VBlank trwa około 1.4 ms. Jeśli GPU nie zdąży zakończyć renderowania przed VBlank, klatka jest pomijana, a ekran wyświetla poprzednią klatkę przez kolejny cykl — jest to odbierane jako stuttering.
Potrójne buforowanie rozwiązuje problem przestojów GPU, dodając trzeci bufor. GPU może rozpocząć renderowanie następnej klatki natychmiast, nawet jeśli jeden z back buffer-ów czeka na VBlank. Zwiększa to FPS przy VSync, ale dodaje dodatkową klatkę opóźnienia. Na urządzeniach mobilnych potrójne buforowanie jest używane w niektórych silnikach gier oraz w Vulkan przez tryb Mailbox.
Wyłączony VSync daje maksymalny FPS i minimalny input lag, ale kosztem artefaktów wizualnych. Dla gier mobilnych i aplikacji z płynną animacją wybór między VSync a jego wyłączeniem to kompromis między ostrością obrazu a responsywnością sterowania.
Screen tearing — poziome rozrywanie, w którym górna część ekranu pokazuje poprzednią klatkę, a dolna — już następną. Dzieje się tak, gdy GPU zmienia bufory w środku cyklu przemiatania ekranu. Na urządzeniach mobilnych tearing jest szczególnie widoczny podczas szybkiego przewijania lub w dynamicznych scenach z wysoką liczbą klatek. Wyświetlacze OLED z ich natychmiastowym czasem reakcji sprawiają, że tearing jest bardziej kontrastowy w porównaniu z LCD.
Intensywność tearingu zależy od stosunku FPS do częstotliwości odświeżania. Przy 60 FPS na ekranie 60 Hz tearing objawia się jako jedna statyczna linia, a przy 300 FPS na 60 Hz — jako wielokrotne faliste rozerwania przesuwające się od góry do dołu. Im wyższy FPS względem częstotliwości odświeżania, tym więcej rozerwań i są one bardziej widoczne.
Input lag przy VSync — opóźnienie między naciśnięciem przycisku a wyświetleniem wyniku na ekranie. Synchronizacja pionowa dodaje średnio jedną klatkę opóźnienia (16.7 ms przy 60 Hz), a przy potrójnym buforowaniu — do dwóch klatek. Dla aplikacji casualowych to opóźnienie jest niezauważalne, ale dla strzelanek, gier walki i gier rytmicznych jest krytyczne: profesjonaliści zauważają opóźnienie nawet 8 ms.
Według badań NVIDIA (2024), średni input lag w CS:GO przy 60 FPS bez VSync wynosi 22 ms, a z VSync — 39 ms. Przy 144 FPS różnica zmniejsza się do odpowiednio 14 vs 18 ms. Na platformach mobilnych input lag VSync jest mniej krytyczny ze względu na wprowadzanie dotykowe, gdzie sprzętowe opóźnienie ekranu dotykowego (10–30 ms) maskuje dodatkowe opóźnienie synchronizacji.
W programowaniu mobilnym VSync jest zarządzany przez API graficzne, silniki gier i ustawienia systemowe OS. iOS zapewnia mniejszą kontrolę, Android — większą przez Vulkan i OpenGL ES. Wybór trybu zależy od typu aplikacji: gry, UI lub wideo.
Unity używa ustawienia QualitySettings.vSyncCount: 0 — wyłączony, 1 — VSync przez każdy VBlank, 2 — przez co drugi (FPS spada o połowę). W Unreal Engine VSync jest zarządzany przez konsolową komendę r.VSync i DefaultEngine.ini. Dla kompilacji mobilnych zaleca się wyłączenie VSync w Unity i użycie własnego ogranicznika FPS, ponieważ wbudowany VSync w Android SurfaceFlinger może tworzyć nieprzewidywalne opóźnienia.
// Unity — zarządzanie VSync i FPS
void Awake()
{
// 0 = VSync wyłączony, 1 = VSync włączony
QualitySettings.vSyncCount = 0;
// Własny ogranicznik FPS zamiast VSync
Application.targetFrameRate = 60;
}
Vulkan daje pełną kontrolę przez VkSwapchainPresentInfo i presentMode: VK_PRESENT_MODE_FIFO_KHR — klasyczny VSync, VK_PRESENT_MODE_MAILBOX_KHR — potrójne buforowanie bez oczekiwania, VK_PRESENT_MODE_IMMEDIATE_KHR — bez synchronizacji. Metal w iOS zarządza VSync przez CAMetalLayer.displaySyncEnabled. Od iOS 14 Apple zaleca używanie displaySyncEnabled = true domyślnie dla wszystkich aplikacji z wyjątkiem gier z arkadowym sterowaniem.
| Tryb | Opis | Opóźnienie |
|---|---|---|
| FIFO | Klasyczny VSync z oczekiwaniem na VBlank | 1 klatka |
| Mailbox | Potrójne buforowanie, odrzucanie starych klatek | 1–2 klatki |
| Immediate | Bez synchronizacji, maksymalny FPS | 0 klatek |
Ogranicznik FPS — alternatywa dla VSync, w której aplikacja programowo ogranicza liczbę klatek na sekundę, nie czekając na VBlank. Takie podejście daje przewidywalne opóźnienie i nie zależy od częstotliwości odświeżania ekranu. Na Androidzie ograniczanie FPS jest realizowane przez Choreographer, na iOS — przez CADisplayLink z ręczną kontrolą czasu wyświetlania.
Tradycyjny VSync ma fundamentalną wadę: jest przywiązany do stałej częstotliwości odświeżania ekranu. Jeśli GPU generuje 45 FPS na ekranie 60 Hz, VSync nie może pokazywać 45 klatek — pokazuje 30 (pomijając co drugi VBlank) lub przełącza między 60 a 30 z nierównymi interwałami. Tworzy to stuttering, który psuje wrażenia z gry bardziej niż tearing.
Adaptive Sync (FreeSync, G-Sync, Apple ProMotion) rozwiązuje ten problem, dynamicznie zmieniając częstotliwość odświeżania ekranu zgodnie z FPS aplikacji. Jeśli aplikacja generuje 47 FPS, ekran przełącza się na 47 Hz — każda klatka jest wyświetlana dokładnie raz, bez rozerwań i stutteringu. ProMotion w iOS automatycznie wybiera częstotliwość od 24 do 120 Hz, balansując płynność i pobór energii.
Na urządzeniach mobilnych Adaptive Sync staje się standardem: iPad Pro (2017+) z ProMotion, flagowce Android z wyświetlaczami LTPO (Samsung Galaxy S23 Ultra, Google Pixel 8 Pro) obsługują dynamiczną częstotliwość odświeżania od 1 do 120 Hz. Dla programisty oznacza to, że VSync w tradycyjnym sensie jest zastępowany przez zarządzanie systemowe — wystarczy ustawić targetFrameRate, a system sam dostosuje częstotliwość odświeżania dla optymalnego balansu płynności i żywotności baterii.
Często zadawane pytania
Nie. W dynamicznych grach (strzelanki, bijatyki) VSync zwiększa input lag bez znaczących korzyści — tearing na mobilnych ekranach OLED jest mniej widoczny ze względu na mały rozmiar wyświetlacza. W grach casualowych i interfejsach UI VSync poprawia odczucie płynności.
VSync zmniejsza pobór energii, ponieważ GPU nie renderuje zbędnych klatek. Przy wyłączonym VSync GPU pracuje z maksymalną częstotliwością, a każda niewyświetlona klatka marnuje energię i nagrzewa urządzenie bez korzyści dla użytkownika.
VSync synchronizuje wyświetlanie klatek z VBlank ekranu, a ogranicznik FPS po prostu ogranicza częstotliwość renderowania w kodzie aplikacji. Ogranicznik FPS nie eliminuje tearingu, ale daje przewidywalne opóźnienie bez przywiązania do częstotliwości odświeżania ekranu.
Gdy GPU nie zdąży ukończyć klatki przed VBlank, VBlank jest pomijany, a klatka jest wyświetlana przez dwa cykle odświeżania. Przy 60 Hz daje to 30 FPS. Potrójne buforowanie łagodzi ten efekt, pozwalając GPU rozpocząć następną klatkę bez oczekiwania.
Tak. iOS ProMotion (iPad Pro, iPhone 13 Pro+) obsługuje dynamiczną częstotliwość 24–120 Hz. Android przez panele LTPO obsługuje 1–120 Hz. Programista nie musi ręcznie tym zarządzać — system wybiera optymalną częstotliwość automatycznie.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również