http:///2017/05/21/VSync%E4%BF%A1%E5%8F%B7/
在我們?cè)敿?xì)分析SurfaceFlinger之前要了解一下VSync信號(hào),為下一節(jié)分析Vsync工作原理打下基礎(chǔ)。 VSync信號(hào)相關(guān)首先我們要了解以下幾個(gè)概念: 屏幕刷新率即 Refresh Rate 或 Scanning Frequency,單位赫茲/Hz,是指設(shè)備刷新屏幕的頻率,該值對(duì)于特定的設(shè)備來(lái)說(shuō)是個(gè)常量,如 60hz。
每一臺(tái)CRT顯示器都有自己的刷新率,其單位是Hz,其數(shù)值是顯示器每秒鐘更新畫面的次數(shù)。不同的顯示器支持再不同分辨率下的不同刷新率。它的范圍可以從低到60高到100。注意它不是你游戲中所提到的那個(gè)FPS。如果你設(shè)置了一個(gè)特定的刷新率,顯示器將一直按照這個(gè)速率刷新畫面。甚至畫面沒有任何的改變。
如下圖,屏幕的刷新過(guò)程是每一行從左到右(行刷新,水平刷新,Horizontal Scanning),從上到下(屏幕刷新,垂直刷新,Vertical Scanning)。當(dāng)整個(gè)屏幕刷新完畢,即一個(gè)垂直刷新周期完成,會(huì)有短暫的空白期,此時(shí)發(fā)出 VSync 信號(hào)。所以,VSync 中的 V 指的是垂直刷新中的垂直/Vertical。 對(duì)于一個(gè)特定的設(shè)備,幀率和刷新頻率沒有必然的大小關(guān)系。 幀率即 Frame Rate,單位 fps,是指 gpu 生成幀的速率,如 33 fps,60fps,越高越好。 我想這里的每一人都明白FPS。它顯示顯示卡在每秒鐘可以描畫多少畫面。這顯然是越高越好。但是對(duì)于快速變化的游戲而言,你的FPS很難一直保持同樣的數(shù)值,他會(huì)隨著你所看到的顯示卡所要描畫的畫面的復(fù)雜程度而變化。 VSync
安卓系統(tǒng)中有 2 種 VSync 信號(hào):屏幕產(chǎn)生的硬件 VSync 和由 SurfaceFlinger 將其轉(zhuǎn)成的軟件 Vsync 信號(hào)。后者經(jīng)由 Binder 傳遞給 Choreographer。 顯示器參數(shù)
TFT LCD 有 vsync,hsync,hspw,hbpd,hfpd, vspw,vbpd, vfpd 等參數(shù),這些參數(shù)都是由以前的 CRT(陰極射線顯像管)帶過(guò)來(lái)的, 而 TFT 液晶跟 CRT 顯示方法根本不同, 至于為什么這些參數(shù)也會(huì)引入到 TFT 中,大概是因?yàn)閂GA(或是DVI)工作原理,上文提到過(guò)。
CRT 側(cè)面看是個(gè)漏斗狀的真空的東東, 根部就是電子槍, 打出的電子撞擊前面的玻璃面上的熒光物質(zhì), 熒光物發(fā)光. 控制電子槍按規(guī)律射出電子, 逐行的打到熒光物質(zhì)上, 打完一行(也即掃描完一行), 就回頭掃描下一行….. 掃描完一個(gè)顯示屏所有的行后, 就是一幅完整的畫面了, 稱為一幀(frame), 掃描過(guò)程如果非??? 人眼看到是一幅完整畫面, 但實(shí)際是一個(gè)個(gè)點(diǎn)發(fā)不同光組成的. 掃描得慢時(shí), 就會(huì)覺得閃爍了(以前聽老師講課, 說(shuō)在他們的年代, 能明顯看到一行一行刷過(guò)的壯觀場(chǎng)景)。 描述方式多數(shù)顯示器選擇從左上角開始, 從左至右, 到了右邊界, 再偏轉(zhuǎn)到左邊界的下一行, 這是所謂的”Z”型掃描。類似地掃描完最后一幀時(shí), 要偏轉(zhuǎn)回左上角起始處, 準(zhǔn)備掃描下一幀。這個(gè)上面那一幅圖描述過(guò)了。
H for Horizontal, V for vertical。在這里 Hsync, Vsync 兩者各表示一種信號(hào), 分別由 HSPW 及 VSPW 兩個(gè)參數(shù)確定信號(hào)持續(xù)時(shí)間, 也就是脈沖的寬度. 在掃描一行中, 首先
因此, 顯示一行時(shí)序?yàn)椋?HSPW -> HBPD -> 掃描數(shù)據(jù) -> HFPD . 類似地, 垂直掃描一幀的時(shí)序:VSPW -> VBPD -> 掃描有效行 -> VFPD .
為什么要有邊框(vbpd, vfpd, hbpd, hfpd)? 按上邊貼出網(wǎng)頁(yè)的說(shuō)法: 舉個(gè)栗子
對(duì)于 TFT LCD, 但這些參數(shù)作用是同樣的. 但如何確定 ? TFT 的 LCD 的 datasheet 中一定得標(biāo)有。 對(duì)照下邊的時(shí)序圖(注: 時(shí)序圖的 Vsync, Hsync 信號(hào)(紅框圈出的)跟上邊講的有點(diǎn)出入, 信號(hào)都是低電平, 而非高電平, 因此編程時(shí)要設(shè)置信號(hào)反相, 如s3c244a 的 LCDCON5的INVLINE 及 INVFRAME 即是干這活的):
參考的時(shí)鐘就是 CLK, 一個(gè) CLK 時(shí)鐘, 完成一個(gè)像素點(diǎn)的顯示。 計(jì)算幀頻率(刷新頻率)的方法就是所有的像素點(diǎn)跟邊沿(邊框,hbpd 之類),同步脈沖的時(shí)間相加, 結(jié)果就是顯示完整一幀所需時(shí)間, 其倒數(shù)即是幀頻率。 Linux 的 LCD 驅(qū)動(dòng)
LCD 驅(qū)動(dòng)主要得完成兩部分, 一是跟 framebuffer 注冊(cè)驅(qū)動(dòng); 二是設(shè)置 LCD 控制器的寄存器, 以適配 LCD。
struct fb_fix_screeninfo 里定義的 pixclock 是像素點(diǎn)的周期, 單位是皮秒, 數(shù)值等于像素點(diǎn)顯示頻率的倒數(shù). 如上圖貼出的表格中, Dclk 那行中, 6.4 Mhz 就是頻率, 頻率倒數(shù)即為周期, 換算出來(lái)為 156250 ps, 約為表中給出的 156 ns. 驅(qū)動(dòng)具體的實(shí)現(xiàn), 要看開發(fā)板對(duì)應(yīng)的驅(qū)動(dòng)源碼文件, 一般位于 kernel_src/drivers/video/ 下,我們以前下的Android源碼,找到對(duì)應(yīng)設(shè)備分支下的,應(yīng)為位于kernel/{branch}/drivers/video/吧。 簡(jiǎn)單描述在手機(jī)平臺(tái),LCD,Camera,TV的接線上,都會(huì)用到PCLK,VSYNC和HSYNC這三個(gè)信號(hào)??梢娺@三個(gè)信號(hào)和顯示關(guān)系非常大。首先我們先看這三個(gè)信號(hào)的作用:
若要顯示一個(gè)640x480的畫面,顯示不正確的時(shí)候,若量PCLK,VSYNC和HSYNC這三個(gè)信號(hào),就可以知道這三個(gè)信號(hào)配置是否有問(wèn)題,一般來(lái)講,這種情況是有公式的:
sensor的同步信號(hào)可以簡(jiǎn)單的理解為sensor向其信號(hào)接收端所發(fā)送的宣告信號(hào)。比如HSYNC,就是sensor這告訴接收端:“HSYNC”有效時(shí)段內(nèi)sensor所有的信號(hào)輸出屬同一行。VSYNC同理,以高電平有效為例,VSYNC置高直到被拉低,這個(gè)區(qū)段sensor所輸出的所有影像數(shù)據(jù)組成一個(gè)frame。同步信號(hào)的頻率決定于pixel clock,比如一行有640個(gè)pixel,那么HSYNC的頻率為:PCLK/(640+dummy);Vsync同理。
VSync 信號(hào)的作用tearing 畫面撕裂首先,我們來(lái)看下,沒有引入 VSync 時(shí),屏幕顯示圖像的工作流程。 如上圖,CPU/GPU 向 Buffer 中生成圖像,屏幕從 Buffer 中取圖像、刷新后顯示。這是一個(gè)典型的生產(chǎn)者——消費(fèi)者模型。理想的情況是幀率和刷新頻率相等,每繪制一幀,屏幕顯示一幀。而實(shí)際情況是,二者之間沒有必然的大小關(guān)系,如果沒有鎖來(lái)控制同步,很容易出現(xiàn)問(wèn)題。 所謂”撕裂”就是一種畫面分離的現(xiàn)象,就象你照一張照片,在旋轉(zhuǎn)哪怕一度再照一張照片,然后把兩張照片的從中間裁開,用一張照片的上半部與另一張的下半部對(duì)接起來(lái)。這樣得到的畫像雖然相似但是上半部和下半部確實(shí)明顯的不同。這就被稱之為視覺現(xiàn)實(shí)上的撕裂。它不會(huì)一直從中間分開,它可能靠近上面也可能下面,分離點(diǎn)可能在屏幕上下移動(dòng),也可能在兩點(diǎn)間前后移動(dòng)。(譯者:原文的作者實(shí)在是啰嗦,其實(shí)就是畫面移動(dòng)較快的時(shí)候,畫面看上去是兩截。這種現(xiàn)象恐怕打游戲的都看到過(guò),最好玩過(guò)PS2游戲的,用模擬器,在比較差的顯卡和CPU上面,撕裂現(xiàn)象更為明顯)。 為什么會(huì)發(fā)生這種現(xiàn)象呢?讓我們舉一個(gè)特定的例子。讓我們假定你的顯示器的刷新率是75Hz, 你真在玩你最喜歡的游戲,而且你現(xiàn)在有100的FPS.這就意味著你的顯示器每秒更新75次畫面,而你的顯示卡每秒更新100次,比你的顯示器快33%。這就意味著在你的顯示器更新畫面的時(shí)間里,顯示卡描畫了1+1/3的畫面。這樣在畫面顯示的時(shí)候,那個(gè)1/3的畫面就會(huì)覆蓋那個(gè)完整畫面上部的1/3。在下次的圖像刷新的時(shí)候,顯示卡會(huì)描畫剩下來(lái)得2/3和新的2/3的畫面。這樣,因?yàn)槠聊坏母轮荒芨袭嬅娓碌?/3,這樣圖像的上部的1/3或是下部的1/3就會(huì)和剩下的畫面合不上。如果畫面的變化不大可能不太會(huì)注意到這一點(diǎn),但是如果你快速的環(huán)顧四周那就會(huì)非常的明顯。 Double Buffer 雙緩沖現(xiàn)在,一個(gè)很普遍的誤解就產(chǎn)生了。一些人認(rèn)為解決這個(gè)問(wèn)題的方法就是簡(jiǎn)單設(shè)置一個(gè)FPS的限制讓FPS不超過(guò)顯示器的刷新率,這樣顯示卡就不會(huì)超過(guò)75FPS,這樣就可以了。真的嗎?錯(cuò)! 在我解釋為什么之前,讓我來(lái)講一下雙倍緩沖。雙倍緩沖一種用來(lái)減輕撕裂問(wèn)題,雖然不是很完全。基本上來(lái)說(shuō)你有一個(gè)顯示緩沖和一個(gè)后備緩沖。當(dāng)顯示器要顯示畫面的時(shí)候,就會(huì)從顯示緩沖里“推出”顯示畫面。顯示卡則在后備緩沖里描畫另外一個(gè)新畫面,當(dāng)描畫完成后則將新畫面考入顯示緩沖里。但是這個(gè)過(guò)程需要時(shí)間,如果顯示器的刷新在拷貝過(guò)程中進(jìn)行的話,顯示器上顯示的仍然是個(gè)”撕裂”的畫面。 VSync 通過(guò)建立一個(gè)不讓在顯示器刷新前將后備緩沖中的畫面拷貝到顯示緩沖中的規(guī)定來(lái)解決這個(gè)問(wèn)題。如果FPS高于刷新率的話,沒有問(wèn)題。后備緩沖的更新完成后,系統(tǒng)處于等待狀態(tài)。當(dāng)顯示器刷新后,后備緩存考入顯示緩存,顯示卡則可以在后備緩存里描畫新的畫面,這樣就很有效的將你的FPS限制在顯示器的刷新率的范圍內(nèi)。 為了解決單緩存的“tearing”問(wèn)題,雙緩存和 VSync 應(yīng)運(yùn)而生。雙重緩存模型如下圖: 兩個(gè)緩存區(qū)分別為 Back Buffer 和 Frame Buffer。GPU 向 Back Buffer 中寫數(shù)據(jù),屏幕從 Frame Buffer 中讀數(shù)據(jù)。VSync 信號(hào)負(fù)責(zé)調(diào)度從 Back Buffer 到 Frame Buffer 的復(fù)制操作,可認(rèn)為該復(fù)制操作在瞬間完成。其實(shí),該復(fù)制操作是等價(jià)后的效果,實(shí)際上雙緩沖的實(shí)現(xiàn)方式是交換 Back Buffer 和 Frame Buffer 的名字,更具體的說(shuō)是交換內(nèi)存地址(有沒有聯(lián)想到那道經(jīng)典的筆試題目:“有兩個(gè)整型數(shù),如何用最優(yōu)的方法交換二者的值?”),通過(guò)二進(jìn)制運(yùn)算“異或”即可完成,所以可認(rèn)為是瞬間完成。(《數(shù)字電路技術(shù)》當(dāng)中有一章節(jié)應(yīng)該講過(guò)運(yùn)算器還是控制器來(lái)著,可以設(shè)計(jì)一個(gè)異或電路。忘了,回去翻一翻~)
雙緩沖的模型下,工作流程這樣的: 在這種模型下,只有當(dāng) VSync 信號(hào)產(chǎn)生時(shí),CPU/GPU 才會(huì)開始繪制。這樣,當(dāng)幀率大于刷新頻率時(shí),幀率就會(huì)被迫跟刷新頻率保持同步,從而避免“tearing”現(xiàn)象。 Jank 掉幀注意,當(dāng) VSync 信號(hào)發(fā)出時(shí),如果 GPU/CPU 正在生產(chǎn)幀數(shù)據(jù),此時(shí)不會(huì)發(fā)生復(fù)制操作。屏幕進(jìn)入下一個(gè)刷新周期時(shí),從 Frame Buffer 中取出的是“老”數(shù)據(jù),而非正在產(chǎn)生的幀數(shù)據(jù),即兩個(gè)刷新周期顯示的是同一幀數(shù)據(jù)。這是我們稱發(fā)生了“掉幀”(Dropped Frame,Skipped Frame,Jank)現(xiàn)象。 讓我們來(lái)看一個(gè)另外一個(gè)不同的例子。讓我們假定你已經(jīng)玩到了你最喜歡的游戲的最后一關(guān),這個(gè)游戲有很好的圖像.你顯示器的刷新率還是在75。但是你的FPS現(xiàn)在只有50了,比刷新率要低33%.這就意味著每次顯示器刷新圖像,你的顯示卡只能畫出下一楨畫面的2/3。讓我們看看它是如何工作的。
如此類推。這樣4次顯示器刷新,我們只能的到2楨的畫面。如果刷新率是75的話,我們只能得到35的FPS.很明顯這個(gè)數(shù)值要低于顯示卡可以帶到的50FPS.這主要就是應(yīng)為顯示卡不得不在描畫后備緩沖上浪費(fèi)時(shí)間。而在此過(guò)程中,后備緩沖上的畫面是不能被拷貝到顯示緩沖。理論上講,雙緩沖的VSync,FPS將是一組不連續(xù)的整數(shù),其等于刷新率/n,n是正整數(shù)。也就是說(shuō),如果你的刷新率是60hz,你能得到的FPS只能是 60,30,20,15,12,10 等等。你可以注意到60到30是一個(gè)相當(dāng)大的差距。只要的顯示卡的FPS在60到30之間,你說(shuō)得到的真實(shí)FPS都將只能等于30! 如下圖,A、B 和 C 都是 Buffer。藍(lán)色代表 CPU 生成 Display List,綠色代表 GPU 執(zhí)行 Display List 中的命令從而生成幀,黃色代表生成幀完成。 現(xiàn)在,你明白為什么有人不喜歡它了。讓我們回到一開始的那個(gè)例子。你在玩你最喜歡的游戲,刷新率是75HZ,100FPS。你打開VSync.游戲就被限制在75FPS,沒有問(wèn)題,沒有撕裂圖像,看起來(lái)不錯(cuò)。你到了一個(gè)圖像特別復(fù)雜的地方,在不用VSync的時(shí)候,你的FPS下降到了60左右。但是你打開了VSync,你的FPS實(shí)際就只有37.5。這樣你的游戲突然從75FPS變成了37.5FPS,不管37.5仍然很流暢但是你一定會(huì)注意到刷新率突然減少了一半。當(dāng)讓如果以下變到25FPS的話,實(shí)際的現(xiàn)實(shí)率可能就只有17.5。本來(lái)還可以玩的游戲,就變成了幻燈片。這就是大家不喜歡它的原因。 如果你的游戲的FPS可以一直穩(wěn)定的大于顯示器的刷新率,VSync是個(gè)不錯(cuò)的東西。但是如果FPS忽大忽小。VSync就是讓人煩的東西。如果你的游戲FPS一直都小于刷新率的話,實(shí)際的FPS要遠(yuǎn)遠(yuǎn)小于顯示卡可以顯示的FPS.看上去就象是VSync降低了你的FPS,但是從技術(shù)角度講,不是應(yīng)為圖像太復(fù)雜,而是因?yàn)閂Sync就是這樣工作的。 Triple Buffer 三緩沖雙重緩存的缺陷在于:當(dāng) CPU/GPU 繪制一幀的時(shí)間超過(guò) 16 ms 時(shí),會(huì)產(chǎn)生 Jank。更要命的是,產(chǎn)生 Jank 的那一幀的顯示期間,GPU/CPU 都是在閑置的。 也不是說(shuō)所有的希望都沒有了。現(xiàn)在的triple-buffering技術(shù)可以用來(lái)解決這個(gè)問(wèn)題。讓我們?cè)賮?lái)看刷新率75。FPS50的例子。
也就是刷新率的2/3,也就是50FPS.triple-buffering理論上講可以避免緩沖寫入是帶來(lái)的延遲現(xiàn)象,這樣就不會(huì)浪費(fèi)時(shí)間。但是triple-buffering并不是適用于所有的游戲。實(shí)際上它并不是普及(這個(gè)文章可能寫的太早,現(xiàn)在triple-buffering已經(jīng)很普及了),而且它也會(huì)影響顯示卡的性能,應(yīng)為它需要更多的顯示內(nèi)存,需要更多時(shí)間在內(nèi)存之間降數(shù)據(jù)拷貝來(lái)拷貝去。但是triple-buffering確實(shí)是一個(gè)很好的方法,既可以消除撕裂畫面又可以不像普通VSync一樣影響你的FPS. 如果有第三個(gè) Buffer 能讓 CPU/GPU 在這個(gè)時(shí)候繼續(xù)工作,那就完全可以避免第二個(gè) Jank 的發(fā)生了! 于是就有了三緩存:
工作原理同雙緩沖類似,只是多了一個(gè) Back Buffer。 三緩沖局限
我希望這篇文章是有用的,可以幫出你理解VSync的工作原理。(特別是不再猶豫是否打開VSync)總之,如果沒有triple-buffering的情況下,如何權(quán)衡Vsync的FPS限制和消除撕裂畫面帶來(lái)的視覺感受,那將完全取決于你個(gè)人的喜好。
所以一定會(huì)有人問(wèn):液晶顯示器的刷新頻率為何不能調(diào)高? 參考
Getting To Know Android 4.1, Part 3: Project Butter - How It Works And What It Added 總結(jié)本篇科普一下VSync,下一節(jié)開始分析它在SurfaceFlinger中的工作流程。 |
|
來(lái)自: astrotycoon > 《vsync》