【Android】從垂直同步到屏幕刷新機制(一)

【Android】從垂直同步到屏幕刷新機制

本文參考以及部分圖片來源:

垂直同步_小科普:“垂直同步”究竟是什么?-CSDN博客

“終于懂了” 系列:Android屏幕刷新機制—VSync、Choreographer 全面理解!-騰訊云開發者社區-騰訊云(這篇博客超級詳細)

打瓦的時候圖像設置這么多,經常在網上看到有提升畫面流暢度的設置參考/最佳性能設置參考等等。

img

image-20250518010044893

抄襲網絡上各路大佬的設置配置,但是并不理解為什么開關某些設置會對畫面造成這么大的影響。今天就從最常見的垂直同步說起,講講屏幕刷新機制。

什么是幀?什么是幀率?什么是刷新率?

首先來解釋一些基礎概念。

1. 幀(Frame)

幀就是一張靜態畫面,類似翻頁動畫書中的一頁紙。視頻、游戲中的動態效果,本質上是通過快速連續播放多幀畫面實現的。

關鍵點

  • 每一幀包含當前時刻畫面的完整信息(比如角色位置、顏色等)。
  • 人眼的視覺暫留效應(約0.1秒)讓連續幀看起來是連貫的動作。
  • 舉例:電影通常每秒播放24幀,游戲可能每秒生成60幀甚至更多。

2. 幀率(Frame Rate / FPS)

每秒生成的幀數,單位是 FPS(Frames Per Second),由內容源(如游戲、視頻)決定。

表示 GPU 在一秒內繪制操作的幀數,單位 fps。例如在電影界采用 24 幀的速度足夠使畫面運行的非常流暢。而 Android 系統則采用更加流程的 60 fps,即每秒鐘GPU最多繪制 60 幀畫面。幀率是動態變化的,例如當畫面靜止時,GPU 是沒有繪制操作的,屏幕刷新的還是buffer中的數據,即GPU最后操作的幀數據。

3. 刷新率(Refresh Rate)

顯示器每秒刷新畫面的次數,單位是 Hz(赫茲),由顯示器硬件決定。

  • 例如:60Hz顯示器每秒刷新60次,144Hz則刷新144次。
  • 每次刷新時,顯示器從顯卡獲取最新幀并顯示。

關鍵點

  • 刷新率是顯示器的“物理上限”。
  • 舉例:即使游戲生成100FPS,60Hz顯示器也只能每秒顯示60幀,多余幀會被丟棄或導致畫面撕裂。

畫面撕裂與掉幀

剛剛圖片帖子中貼主提到,在調整完設置之后,不會有畫面撕裂和掉幀的現象了。這兩個詞匯我們平時經常提到,不妨思考兩個問題:

掉幀,是說 這一幀延遲顯示 還是 丟棄不再顯示 ?為什么?

顯示器為什么會出現畫面撕裂的問題?為什么兩個幀會同時顯示在屏幕上?

帶著這個問題我們來探尋一下,首先依然是給出結論。

1. 畫面撕裂(Screen Tearing)

是什么?

顯示器在刷新過程中,同時顯示了多個幀的部分內容,導致畫面被“撕裂”成上下兩部分或多塊不一致的圖像(如下圖)。

img

為什么發生?

  • 幀率(FPS) ≠ 刷新率(Hz):當顯卡輸出幀的速度(FPS)與顯示器刷新率不同步時,顯示器可能在一次刷新中途切換到新幀,導致新舊幀混雜。
  • 舉例:顯卡每秒生成100幀(100FPS),顯示器是60Hz。顯卡生成幀的速度遠快于顯示器刷新,顯示器在刷新到一半時可能突然收到新幀,導致畫面撕裂。

如何解決?

  • 開啟垂直同步(V-Sync):強制顯卡等待顯示器刷新完成再輸出新幀。
  • 使用自適應同步技術(如G-Sync/FreeSync):讓顯示器動態調整刷新率,匹配顯卡輸出的幀率。
  • 限制幀率:手動將游戲幀率限制在顯示器刷新率以內(如60FPS配60Hz顯示器)。

2. 掉幀(Frame Drops)

是什么?

內容源(如游戲、視頻)實際生成的幀數低于預期幀率,導致畫面卡頓、不連貫。例如:

  • 游戲標稱60FPS,但因性能不足,實際只能生成40FPS → 每秒少了20幀,動作變得卡頓。
  • 視頻播放時因解碼或帶寬問題,部分幀未能及時加載 → 畫面突然“跳幀”。

為什么發生?

  • 硬件性能不足:顯卡/CPU無法及時渲染足夠幀(常見于高畫質游戲或復雜場景)。
  • 軟件優化差:程序代碼效率低,導致幀生成不穩定。
  • 外部干擾:網絡延遲(在線視頻/直播)、硬盤讀取速度慢(加載貼圖卡頓)等。

寫到這里我們基本上了解了,畫面撕裂是由于多個幀的內容被同時顯示在屏幕上,而掉幀是實際生成的幀數低于預期幀率。而垂直同步可以強制顯卡等待顯示器刷新完成再輸出新幀,從而幫助我們解決畫面撕裂的問題,但可能導致掉幀的問題。

但是開頭的兩個問題仍未得到解決,并且我們依舊沒有真正了解垂直同步和畫面撕裂的內部原因。或許我們需要更加深入地學習一下顯示系統的基礎知識。

顯示系統基礎知識

基礎架構與組件角色

  • CPU:負責生成幀的邏輯數據。處理內容包括應用狀態(如游戲角色坐標、UI控件位置)、物理計算、動畫邏輯等。輸出為圖形渲染所需的非像素化數據(如頂點坐標、紋理坐標、材質屬性)。
  • GPU:接收CPU傳遞的圖形數據,通過渲染管線(頂點著色→光柵化→像素著色)生成最終像素圖像,寫入圖形緩沖區(Graphic Buffer)。渲染速度取決于著色復雜度(如光照、抗鋸齒、分辨率)。
  • 顯示器:以固定刷新率(如60Hz)從緩沖區讀取像素數據,通過逐行掃描將圖像顯示到屏幕。每次刷新周期包含有效掃描期(Active)和垂直空白期(VBlank)。

逐行掃描

定義:逐行掃描指顯示器從上到下、從左到右依次繪制每一行像素,完整顯示一幀畫面后,再開始下一幀的掃描。

關鍵特征

  • 順序性:每一幀的所有行(如1080p的1920×1080=2073600行)按物理順序連續掃描。
  • 完整性:每次刷新周期(如16.67ms@60Hz)內,屏幕顯示完整的單一幀畫面。
  • 同步信號:依賴**水平同步(HSync)垂直同步(VSync)**信號控制掃描節奏。

單緩存

早期的顯示系統采用單緩存模式(Single Buffering),即僅使用一個緩沖區(Frame Buffer)供GPU寫入渲染數據,同時顯示器從中讀取數據刷新屏幕。這種設計雖然簡單,但存在以下核心問題:

畫面撕裂(Screen Tearing)

顯示器在逐行掃描過程中,若GPU在屏幕刷新中途更新緩沖區數據,會導致屏幕上半部分顯示舊幀、下半部分顯示新幀,畫面被“撕裂”為不連貫的兩部分。這主要是因為GPU和顯示器異步訪問同一緩沖區,缺乏同步機制。顯示器無法感知GPU寫入時機,可能讀取到部分更新的幀。

示例:假設顯示器以60Hz刷新(16.6ms/幀),GPU每10ms渲染一幀:

  • T=0ms:顯示器開始掃描第N幀。
  • T=8ms:GPU完成第N+1幀并寫入緩沖區。
  • T=8~16.6ms:顯示器繼續掃描,下半部分顯示第N+1幀,上半部分仍為第N幀,畫面撕裂。
讀寫沖突(Read-Write Contention)

GPU和顯示器同時訪問同一緩沖區時,可能導致數據損壞或需要復雜的鎖機制,降低系統效率。

  • GPU寫入速度與顯示器讀取速度不匹配(如GPU寫入速度遠快于顯示器刷新速度)。
  • 單緩存無讀寫分離機制,硬件需頻繁仲裁緩沖區訪問權。

雙緩存

為克服單緩存缺陷,現代顯示系統引入**雙緩存(Double Buffering)垂直同步(VSync)**機制:

雙緩存結構

  • Front Buffer:僅用于顯示器讀取(當前顯示幀)。
  • Back Buffer:僅用于GPU寫入(下一渲染幀)。
  • 緩沖區交換:在顯示器垂直空白期(VBlank)交換兩者內存地址(非數據拷貝)。

VSync同步

  • 顯示器在VBlank期間發送同步信號,強制GPU在此時完成緩沖區交換。
  • 確保顯示器每次刷新都讀取完整幀,消除撕裂與讀寫沖突。

雙緩存結構

雙緩存的核心思想是通過兩個獨立的緩沖區實現渲染與顯示的物理隔離。**Front Buffer(前緩沖區)專門用于顯示器逐行掃描輸出當前幀,而Back Buffer(后緩沖區)**則留給GPU自由寫入下一幀的渲染數據。

這兩個緩沖區各司其職——顯示器在刷新周期內持續從前緩沖區讀取像素,而GPU無需等待顯示器的進度,可以全速向后緩沖區填充新幀。這種分離徹底避免了單緩存模式下讀寫沖突的問題,GPU和顯示器不再爭奪同一塊內存的訪問權,數據損壞和鎖競爭的風險也隨之消失。

垂直同步

然而,雙緩存本身并不能完全解決畫面撕裂。如果緩沖區交換的時機不當,顯示器仍可能掃描到部分更新的幀。此時,垂直同步(VSync)便成為關鍵的同步機制。其工作原理基于顯示器硬件的物理特性:每一幀掃描完成后,顯示器會從屏幕右下角回到左上角,開始下一幀的掃描,這段短暫的返回時間稱為垂直空白期(VBlank)

VSync信號正是由顯示器在VBlank開始時發出的一個脈沖,它像交通信號燈一樣,強制GPU在此時間窗口內完成緩沖區的交換。具體來說,當VSync信號觸發時,系統會將Front Buffer和Back Buffer的內存地址瞬間互換(而非拷貝數據),確保顯示器下一幀掃描的始終是完整的、已渲染好的圖像。這種同步機制從根本上消除了畫面撕裂的可能,因為顯示器每次刷新都從全新的完整幀開始,新舊幀的切換被嚴格限制在屏幕無輸出的“安全期”內。

雙緩存帶來的問題

盡管雙緩存+VSync的組合解決了撕裂問題,但也引入了新的挑戰。**輸入延遲(Input Lag)**是其中最顯著的影響——由于GPU必須等待VSync信號才能開始渲染下一幀,玩家的操作(如點擊鼠標或觸摸屏幕)需要多等待一個刷新周期(如16.6ms@60Hz)才能反映到畫面上,這對競技類游戲或實時交互場景是致命的。

另一個問題是幀率鎖死:若GPU無法在下一個VSync信號到來前完成渲染(例如復雜場景下渲染耗時超過16.6ms),顯示器只能重復顯示上一幀,導致幀率驟降(如60Hz→30Hz),形成卡頓(Jank)。這種“全有或全無”的機制使得性能波動被放大,幀率只能以刷新率的整數倍(1/2、1/3)跌落,用戶體驗呈現明顯的階梯式劣化。

借用“終于懂了” 系列:Android屏幕刷新機制—VSync、Choreographer 全面理解!-騰訊云開發者社區-騰訊云博客中的圖。

img

在第三幀時,GPU未完成計算,故而發生了重復顯示,只能將第二幀顯示兩次,而后等到下一次VSync再顯示。

輸入延遲

在雙緩存+VSync的架構下,輸入延遲的累積源自同步機制對渲染管線的強制阻塞。具體流程如下:

  1. 操作觸發:玩家點擊鼠標或觸摸屏幕(T=0ms)。
  2. CPU處理:游戲引擎接收到輸入事件,更新角色位置或射擊邏輯(耗時1ms)。
  3. GPU渲染:根據新數據生成下一幀(耗時10ms),但渲染完成時(T=11ms),若距離下一個VSync信號(T=16.6ms)還有5.6ms,GPU必須等待。
  4. 緩沖區交換:直到T=16.6ms(VSync觸發),新幀才被提交至顯示器。
  5. 顯示延遲:顯示器從T=16.6ms開始掃描,到T+16.6ms=33.2ms完成顯示。

總延遲:從操作觸發到畫面反饋需33.2ms(操作1ms + 渲染10ms + 等待5.6ms + 顯示16.6ms)。

  • 對比無VSync:若關閉VSync,GPU完成渲染后立即交換緩沖區,延遲可降至27.6ms(操作1ms + 渲染10ms + 顯示16.6ms)。

下次打瓦的時候輸了就可以說自己不小心把垂直同步打開了,導致機器反應慢了(

幀率鎖死

當GPU渲染速度無法匹配顯示器刷新率時,VSync的“全有或全無”規則導致幀率呈離散式下降:

案例:60Hz顯示器 + GPU渲染耗時20ms/幀

  1. VSync 1(T=0ms):GPU開始渲染第1幀至Back Buffer。
  2. VSync 2(T=16.6ms):第1幀未完成(僅渲染16.6ms),無法交換緩沖區,顯示器繼續顯示舊幀(第0幀)。
  3. T=20ms:GPU完成第1幀,但需等待至VSync 3(T=33.3ms)才能交換。
  4. VSync 3(T=33.3ms):顯示第1幀,GPU開始渲染第2幀。
  5. VSync 4(T=50ms):第2幀耗時20ms,同樣未完成,顯示器重復顯示第1幀。

結果:實際幀率降至30Hz(1幀/33.3ms),而非理論上的50Hz(1000ms/20ms=50FPS)。幀率被強制對齊到刷新率的分數倍(60/2=30Hz、60/3=20Hz等),形成“階梯式卡頓”。

三緩存

雙緩存與垂直同步(VSync)這一設計通過物理隔離的緩沖區與精準的時序控制,確實解決了撕裂問題,卻也帶來了輸入延遲與幀率鎖死的新挑戰。

為了突破這些限制,現代技術轉向了更靈活的協同機制,其中最具代表性的便是三緩存(Triple Buffering)自適應同步(G-Sync/FreeSync)

依然借用一下這張圖。

img

三緩存在雙緩存的Front Buffer和Back Buffer基礎上,增加一個備用緩沖區(Extra Back Buffer),形成三個緩沖區的環形隊列。其核心邏輯是允許GPU在等待VSync期間繼續渲染后續幀,而非強制空閑。

優勢

減少連續卡頓:單幀超時不會阻塞后續幀的渲染,避免Jank鏈式反應。

硬件利用率提升:GPU在等待VSync期間可繼續工作,算力浪費減少。

代價

內存占用增加:1080p@32位色深下,單緩沖區需8MB,三緩存額外消耗8MB。

潛在延遲增加:幀可能多等待一個VSync周期顯示(如第1幀在33.3ms而非16.6ms顯示)。

自適應同步

自適應同步的核心思想是讓顯示器的刷新率實時匹配GPU的輸出幀率。這一過程依賴三個關鍵技術組件:

  1. 可變刷新率顯示器:硬件支持刷新率在特定范圍內連續變化(如FreeSync的30-144Hz、G-Sync的1-240Hz)。
  2. 同步控制器:集成于顯示器或顯卡中的芯片,負責監測GPU的幀提交狀態,并動態調整顯示器的時序信號。
  3. 通信協議:通過DisplayPort或HDMI接口傳遞同步信號,確保GPU與顯示器的指令實時互通。

當GPU完成一幀渲染時,同步控制器立即通知顯示器:“這一幀已就緒,現在開始掃描!”顯示器隨即啟動逐行刷新,并在掃描完成后立即準備接收下一幀,而非等待固定的VSync周期。例如,若GPU以45FPS的速度渲染,顯示器會將刷新率精準調整為45Hz,每22.2ms刷新一次;若GPU突然加速到90FPS,顯示器也瞬間切換至90Hz,每11.1ms刷新一次。這種“幀到幀”的同步徹底消除了傳統VSync的等待期,使得每一幀的顯示時機與GPU的輸出完全契合。

結語

雖然標題帶了個Android,但是實際上本文并未特地解析Andorid屏幕刷新機制,這些留到下一期再說~

下一期我們將解析Choreographer的源碼,了解一下Android Display系統!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81704.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81704.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81704.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ACL完全解析:從權限管理到網絡安全的核心防線

訪問控制列表(ACL)是一種用于管理資源訪問權限的核心安全機制,廣泛應用于操作系統和網絡設備中。以下是對ACL的詳細解析: 1. 基本概念 定義:ACL是由多個訪問控制條目(ACE)組成的列表&#xff0…

代碼審計-php框架開發,實戰tp項目,打擊微交易,源碼獲取,擴大戰果

實戰,不安全寫法引發的注入 這個bc靶場源碼沒有,看老師演示 打開很明顯的tp框架源碼 拿到tp框架之后第一步,搜索版本信息5.0.5 兩個思路 1.代碼的不安全寫法 2.版本自身存在的漏洞 全局搜索where看看也沒有不安全的 哎?&…

大模型的實踐應用43-基于Qwen3(32B)+LangChain框架+MCP+RAG+傳統算法的旅游行程規劃系統

大家好,我是微學AI,今天給大家介紹一下大模型的實踐應用43-基于Qwen3(32B)+LangChain框架+MCP+RAG+傳統算法的旅游行程規劃系統。本報告將闡述基于大模型Qwen3(32B)、LangChain框架、MCP協議、RAG技術以及傳統算法構建的智能旅游行程規劃系統。該系統通過整合多種技術優勢,實…

Jsoup庫和Apache HttpClient庫有什么區別?

Jsoup 和 Apache HttpClient 是兩個功能不同的庫,它們在 Java 開發中被廣泛使用,但用途和功能有明顯的區別: Jsoup 用途:Jsoup 是一個用于解析 HTML 文檔的庫。它提供了非常方便的方法來抓取和解析網頁內容,提取和操作…

騰訊云存儲原理

我們來詳細展開你提到的兩個核心結構概念: 一、“基于分布式文件系統 對象存儲技術” 是什么? 1. 分布式文件系統(DFS)基礎 分布式文件系統是一種支持將數據分布在多個存儲節點上、并對上層用戶透明的文件系統。騰訊云COS雖然是…

python fastapi + react, 寫一個圖片 app

1. 起因, 目的: 上廁所的時候,想用手機查看電腦上的圖片,但是又不想點擊下載。此app 應運而生。 2. 先看效果 單擊圖片,能放大圖片 3. 過程: 過程很枯燥。有時候, 有一堆新的想法。 但是做起來太麻煩,…

Kubernetes控制平面組件:Kubelet詳解(五):切換docker運行時為containerd

云原生學習路線導航頁(持續更新中) kubernetes學習系列快捷鏈接 Kubernetes架構原則和對象設計(一)Kubernetes架構原則和對象設計(二)Kubernetes架構原則和對象設計(三)Kubernetes控…

QT6 源(111):閱讀與注釋菜單欄 QMenuBar,進行屬性與成員函數測試,信號與槽函數測試,并給出源碼

(1) (2) (3) (4) (5) (6) (7)以下源代碼來自于頭文件 qmenubar . h : #ifndef QMENUBAR_H #defi…

Leetcode 3552. Grid Teleportation Traversal

Leetcode 3552. Grid Teleportation Traversal 1. 解題思路2. 代碼實現 題目鏈接:3552. Grid Teleportation Traversal 1. 解題思路 這一題的話核心就是一個廣度優先遍歷,我們只需要從原點開始,一點點考察其所能到達的位置,直至…

2023CCPC河南省賽暨河南邀請賽個人補題ABEFGHK

Dashboard - 2023 CCPC Henan Provincial Collegiate Programming Contest - Codeforces 過題難度:A H F G B K E 銅獎: 2 339 銀獎: 3 318 金獎: 5 523 A: 直接模擬 // Code Start Here int t;cin >> t;while(t-…

如何用Python批量解壓ZIP文件?快速解決方案

如何用Python批量解壓ZIP文件?快速解決方案 文章目錄 **如何用Python批量解壓ZIP文件?快速解決方案**代碼結果詳細解釋 話不多說,先上干貨!!! 代碼 import os import zipfiledef unzip_file(dir_path: str…

Spring Boot 的高級特性與經典的設計模式應用

目錄 1. 設計模式在 Spring Boot 中的應用 1.1 單例模式:Bean 管理與全局實例 1.1.1 Spring 中的單例 Bean 1.1.2 自定義單例實現 1.1.3 單例模式的優勢 1.2 工廠模式:動態創建 Bean 1.2.1 Spring 的工廠方法 1.2.2 自定義工廠類 1.2.3 工廠模式…

在Excel中使用函數公式時,常見錯誤對應不同的典型問題

在Excel中使用函數公式時,常見錯誤對應不同的典型問題 1. #DIV/0!(除以零錯誤)2. #N/A(值不可用)3. #NAME?(名稱錯誤)4. #NULL!(空交集錯誤)5. #NUM!(數值錯…

【cursor疑惑】cursor續杯后使用agent對話時,提示“需要pro或商業訂閱的用戶才能使用“

背景 cursor的pro會員體驗過期了,想再次體驗deepseek、Claude等agent對話提示:“免費版本不可以使用agent對話功能(英文忘記截圖了,大意是這樣)”。 處理方法 Step-1:再次續杯cursor的pro會員14天體驗 詳情,見:【c…

解決qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed

可以參考:解決qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed-CSDN博客 講的是程序執行目錄下可能缺少了: libssl-1_1-x64.dll 和 libcrypto-1_1-x64.dll 庫文件,將其復制到可執行文件exe的同級目錄下即可…

白楊SEO:不到7天,白楊SEO博客網站百度搜索顯示和排名恢復正常!順帶說說上海線下GEO聚會分享和播客紅利

大家好,我是白楊SEO,專注SEO十年以上,全網SEO流量實戰派,AI搜索優化研究者。 5月開始,明顯就忙起來了,不管是個人陪跑還是企業顧問,不管是需要傳統SEO還是新媒體流量,還是當下這個A…

FART 自動化脫殼框架簡介與脫殼點的選擇

版權歸作者所有,如有轉發,請注明文章出處:https://cyrus-studio.github.io/blog/ FART簡介 ART 環境下基于主動調用的自動化脫殼方案,可以解決函數抽取殼。 關于函數抽取殼的實現原理可以參考:基于 art 下的類加載機…

卷積神經網絡進階:轉置卷積與棋盤效應詳解

【內容摘要】 本文深入解析卷積神經網絡中的轉置卷積(反卷積)技術,重點闡述標準卷積與轉置卷積的計算過程、轉置卷積的上采樣作用,以及其常見問題——棋盤效應的產生原因與解決方法,為圖像分割、超分辨率等任務提供理論…

Redis進階知識

Redis 1.事務2. 主從復制2.1 如何啟動多個Redis服務器2.2 監控主從節點的狀態2.3 斷開主從復制關系2.4 額外注意2.5拓撲結構2.6 復制過程2.6.1 數據同步 3.哨兵選舉原理注意事項 4.集群4.1 數據分片算法4.2 故障檢測 5. 緩存5.1 緩存問題 6. 分布式鎖 1.事務 Redis的事務只能保…

SDC命令詳解:使用get_libs命令進行查詢

相關閱讀 SDC命令詳解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 get_libs命令用于創建一個庫對象集合,關于設計對象和集合的更詳細介紹,可以參考下面的博客。需要注意的是,在有些工具中還存在…