資料介紹
作者:Ady Abraham, Software Engineer
來源:谷歌開發者
長久以來,手機屏幕刷新率都是 60Hz。應用和游戲開發者也習慣了假定刷新率為 60Hz,也就是每 16.6ms 生成一幀,而且這樣開發出來的應用和游戲都會正常進行。但現在的情況已經不同了。最新的旗艦級設備往往會搭載刷新率更高的屏幕,可以帶來更流暢的動畫效果、更低的延遲,從而獲得更好的整體用戶體驗。還有一些設備支持可變刷新率,比如 Pixel 4,它支持 60Hz 和 90Hz 兩種刷新率。
60Hz 的屏幕每 16.6ms 刷新一次顯示內容。這意味著圖像顯示的時間是 16.6ms 的倍數 (16.6ms、33.3ms、50ms 等)。支持多種刷新率的屏幕則帶來了更多的選擇,這些屏幕能以不同的速度進行渲染,并且不會出現抖動。例如,一個無法維持 60fps 渲染的游戲,在 60Hz 的屏幕上必須一路降到 30fps 才能確保流暢無抖動 (因為顯示器只能以 16.6ms 的倍數周期呈現圖像,所以 60Hz 的下一檔可用幀速是每 33.3ms 顯示一幀,即 30fps)。而在 90Hz 設備上,同樣的游戲只需要下降到 45fps (每幀 22.2ms) 即可,這就為用戶帶來了更流暢的體驗。而同時支持 90Hz 和 120Hz 的設備,則可以用每秒 120、90、60 (120/2)、45 (90/2)、40 (120/3)、30 (90/3)、24 (120/5) 等幀率流暢地呈現內容。
高頻率渲染
渲染頻率越高,就越難維持幀率,因為只有更少的時間完成相同的工作量。要在 90Hz 下進行渲染,應用需要在 11.1ms 內生成一幀,與此相比,在 60Hz 時則有 16.6ms 來生成一幀。
為了詳細說明這一點,我們來看看 Android UI 的渲染流水線。我們可以將幀渲染大致分為五個流水線階段:
① 應用的 UI 線程處理輸入事件,調用應用的回調,并更新視圖 (View) 層次結構中記錄的繪圖命令列表;
② 應用的 RenderThread 將記錄的命令發送到 GPU ;
③ GPU 繪制這一幀;
④ SurfaceFlinger 是負責在屏幕上顯示不同應用窗口的系統服務,它會組合出屏幕應該最終顯示出的內容,并將畫面提交給屏幕的硬件抽象層 (HAL);
⑤ 屏幕最終呈現該幀的內容。
整個流水線由 Android Choreographer 控制。Choreographer 基于顯示垂直同步 (vsync) 事件,它表示屏幕開始掃描出圖像并更新顯示像素的時間點。雖然 Choreographer 基于 vsync 事件,但對應用和 SurfaceFlinger 來說,其喚醒偏移量不同。下圖展示了在 Pixel 4 設備上運行的流水線,應用在 vsync 事件后 2ms 被喚醒,SurfaceFlinger 則在 vsync 事件后 6ms 被喚醒。這樣一來,應用產生一幀畫面的時間為 20ms,SurfaceFlinger 組合畫面內容的時間則為 10ms。

當以 90Hz 頻率運行時,應用依然在 vsync 事件后 2ms 被喚醒。然而,SurfaceFlinger 在 vsync 事件后 1ms 被喚醒,同樣有 10ms 的時間來合成屏幕內容。但這樣一來應用只有 10ms 來渲染一幀畫面,這時間就非常窘迫了:

為了緩解這種情況,Android 的 UI 子系統采用了預先渲染 (render ahead,指維持一幀的啟動時間不變,但推遲其呈現時間) 來深化流水線,并將幀的呈現時間推遲一個 vsync。這樣一來,應用可以有 21ms 的時間來生成一幀,同時確保維持 90Hz 的吞吐量。

一些應用,包括大多數游戲,都有自己自定義的渲染流水線。這些流水線可能會有更多或更少的階段,具體取決于它們要完成的任務。一般來說,流水線越深,可以并行執行的階段就越多,整體的吞吐量也會相應增加。但另一方面,這樣可能會增加單幀的延遲 (延遲量為 number_of_pipeline_stages x longest_pipeline_stage)。這中間如何取舍需要開發者審慎考慮。
利用可變刷新率
如上所述,可變刷新率允許我們使用更多樣的渲染頻率。對于可以控制渲染速度的游戲,以及需要以特定速率呈現內容的視頻播放器來說,這一點尤其有用。例如,要在 60Hz 的顯示器上播放 24fps 的視頻,我們需要使用 3:2 pulldown 算法,這就會產生抖動。但是,如果設備的屏幕可以原生顯示 24fps 的內容 (24/48/72/120Hz),就無需使用 pulldown 算法,自然也就不會出現抖動了。
- 3:2 pulldown 算法
https://en.wikipedia.org/wiki/Three-two_pull_down
設備運行時的刷新率是由 Android 平臺控制的。應用和游戲可以通過多種方法影響刷新率 (下面會有解釋),但最終結果由平臺決定。尤其是當屏幕上同時有多個應用時,這一點至關重要: 平臺需要滿足所有應用的刷新率需求。24fps 視頻播放器就是一個很好的例子。24Hz 對于視頻播放來說可能很好,但對于響應式 UI 來說就很糟糕了。如果一個推送通知的動畫只有 24Hz,感覺就會很扎眼。在這種情況下,平臺會選擇讓屏幕上的內容都顯示良好的刷新率。
為此,應用可能需要知道當前設備的刷新率。可以通過以下方法來實現:
- NDK
使用 AChoreographer_registerRefreshRateCallback 注冊回調 (API 級別30)。
- DisplayManager.DisplayListener
https://developer.android.google.cn/reference/android/hardware/display/D...(android.hardware.display.DisplayManager.DisplayListener,%20android.os.Handler)
- Display.getRefreshRate
https://developer.android.google.cn/reference/android/view/Display#getRe...()
- AChoreographer_registerRefreshRateCallback
https://developer.android.google.cn/ndk/reference/group/choreographer#ac...
應用可以通過在其 Window 或 Surface 上設置幀率來影響設備刷新率。這是 Android 11 中引入的一個新功能,允許平臺了解應用的渲染需求。應用可以調用以下方法之一:
- SDK
Surface.setFrameRate
https://developer.android.google.cn/reference/android/view/Surface#setFr...(float,%20int)SurfaceControl.Transaction.setFrameRate
https://developer.android.google.cn/reference/android/view/SurfaceContro...(android.view.SurfaceControl,%20float,%20int)
- NDK
ANativeWindow_setRrameRate
https://developer.android.google.cn/ndk/reference/group/a-native-window#...ASurfaceTransaction_setFrameRate
https://developer.android.google.cn/ndk/reference/group/native-activity#...
關于如何使用這些 API,請參考幀率指南文檔。
系統會根據 Window 或 Surface 上設置的幀率選擇最合適的刷新率。
在較舊的 Android 版本 (Android 11 之前) 中并不存在 setFrameRate API,這時應用仍然可以通過直接將 WindowManager.LayoutParams.preferredDisplayModeId 設置為 Display.getSupportedModes 中的可用模式之一來影響刷新率。從 Android 11 開始,我們不建議大家采用這種方法,因為平臺會不知道應用的渲染意圖。例如,如果一個設備支持 48Hz、60Hz 和 120Hz,屏幕上有兩個應用分別調用 setFrameRate(60, …) 和 setFrameRate(24, …),那么平臺可以選擇 120Hz 來同時滿足這兩個應用。而如果這些應用使用了 preferredDisplayModeId,它們很可能會把模式設置為 60Hz 和 48Hz,那這時平臺就無法使用 120Hz 了。這時平臺只能從 60Hz 或 48Hz 中選擇一個,從而影響到另一個應用的顯示效果。
- WindowManager.LayoutParams.preferredDisplayModeId
https://developer.android.google.cn/reference/android/view/WindowManager...
- Display.getSupportedModes
https://developer.android.google.cn/reference/android/view/Display#getSu...()
總結
刷新率不一定是 60Hz——不要想當然地認為它一定會是 60Hz,也不要基于歷史經驗作出硬性假設。
刷新率并不總是恒定的——如果您想了解實際的刷新率,就需要注冊一個回調來知曉刷新率的變動,并相應地更新您應用內部的數據。
如果您沒有使用 Android UI 工具包,而使用自定義的渲染器,請考慮根據當前的刷新率來改變您的渲染流水線。通過使用 OpenGL 上的 eglPresentationTimeANDROID 或 Vulkan 上的 VkPresentationTimesInfoGOOGLE 設置一個呈現時間戳,即可深化流水線。設置呈現時間戳可以向 SurfaceFlinger 指示何時呈現圖像。如果設置為未來的幾幀,它就會按照設置的幀數加深流水線。前文例子中的 Android UI 將呈現時間設置成了 frameTimeNanos + 2 * vsyncPeriod。
注: frameTimeNanos 從 Choreographer 獲取;vsyncPeriod 從 Display.getRefreshRate() 獲取。
- eglPresentationTimeANDROID
https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_pres...
- VkPresentationTimesInfoGOOGLE
https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/Vk...
使用 setFrameRate API 告訴平臺您的渲染意圖,平臺會選擇合適的刷新率來匹配不同的需求。
您應該只在必要時才使用 preferredDisplayModeId: 當 setFrameRate API 不可用時,或是當您需要使用非常特定的模式時。
最后,請您深入了解一下 Android 的幀同步庫。這個庫可以為您的游戲妥善處理幀同步,并使用前文中的方法來處理多種刷新率。
本文轉自: 谷歌開發者(Google_Developers),作者:Ady Abraham, Software Engineer,
轉載此文目的在于傳遞更多信息,版權歸原作者所有。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
- 使用Edge Impulse在pico上进行手势识别0次下载
- 使用MCP3008在Raspberry Pi上进行模拟输入1次下载
- 在4片级联参考设计板上进行发射天线的连续波测试0次下载
- 使用CASP在Arduino上进行机器学习0次下载
- 允许在Terps Racing EV22赛车上进行 CAN通信的CAN屏蔽2次下载
- AndroidSVG图片解析和渲染工具1次下载
- 如何测试数字示波器的波形捕获率27次下载
- Android手机与单片机之间进行蓝牙通信的方法和程序免费下载18次下载
- 使用android仿真器进行电池的仿真介绍虚拟设备的实现和使用1次下载
- 如何使用ARM虚拟化扩展进行Android内核动态度量方法说明8次下载
- Android Studio学习教程(电子书+源码)资料下载0次下载
- VR体验的分辨率和刷新率的解析13次下载
- android 水滴动画版下拉刷新0次下载
- 电脑屏幕分辨率设置工具59次下载
- 提高扫描屏视觉刷新率的解决方案28次下载
- 杰和课堂|一文讲清影响视觉体验的「刷新率」1741次阅读
- 示波器波形刷新率测量方法详解2113次阅读
- 基于在广泛的计算平台上进行高效渲染的神经场体系结构626次阅读
- 使用Devtron在Kubernetes多集群上进行开发1035次阅读
- Android Studio Chipmunk更新后的卡顿检测界面2006次阅读
- 示波器的采集原理、波形刷新率的作用及死区时间的计算9549次阅读
- 浅谈示波器的刷新率和波形捕获率测量4090次阅读
- 如何才能测量示波器的刷新率详细方法说明6223次阅读
- 基于FPGA的高分辨率高刷新率图像采集系统设计1417次阅读
- 屏幕刷新率60Hz和90Hz的区别44236次阅读
- 怎样提高LED显示屏的刷新率?10164次阅读
- 屏幕刷新率越高越好吗?小心被刷新率参数骗了74960次阅读
- 什么是波形刷新率?影响波形刷新率的因素有哪些?6028次阅读
- 基于FPGA的数字示波器波形合成器研究3148次阅读
- 一文读懂PS VR的120Hz刷新率技术原理7047次阅读
下載排行
本周
- 1電子電路原理第七版PDF電子教材免費下載
- 0.00 MB | 1491次下載 | 免費
- 2單片機典型實例介紹
- 18.19 MB | 95次下載 | 1 積分
- 3S7-200PLC編程實例詳細資料
- 1.17 MB | 27次下載 | 1 積分
- 4筆記本電腦主板的元件識別和講解說明
- 4.28 MB | 18次下載 | 4 積分
- 5開關電源原理及各功能電路詳解
- 0.38 MB | 11次下載 | 免費
- 6100W短波放大電路圖
- 0.05 MB | 4次下載 | 3 積分
- 7基于單片機和 SG3525的程控開關電源設計
- 0.23 MB | 4次下載 | 免費
- 8基于AT89C2051/4051單片機編程器的實驗
- 0.11 MB | 4次下載 | 免費
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234313次下載 | 免費
- 2PADS 9.0 2009最新版 -下載
- 0.00 MB | 66304次下載 | 免費
- 3protel99下載protel99軟件下載(中文版)
- 0.00 MB | 51209次下載 | 免費
- 4LabView 8.0 專業版下載 (3CD完整版)
- 0.00 MB | 51043次下載 | 免費
- 5555集成電路應用800例(新編版)
- 0.00 MB | 33562次下載 | 免費
- 6接口電路圖大全
- 未知 | 30320次下載 | 免費
- 7Multisim 10下載Multisim 10 中文版
- 0.00 MB | 28588次下載 | 免費
- 8開關電源設計實例指南
- 未知 | 21539次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935053次下載 | 免費
- 2protel99se軟件下載(可英文版轉中文版)
- 78.1 MB | 537793次下載 | 免費
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420026次下載 | 免費
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234313次下載 | 免費
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費
- 6電路仿真軟件multisim 10.0免費下載
- 340992 | 191183次下載 | 免費
- 7十天學會AVR單片機與C語言視頻教程 下載
- 158M | 183277次下載 | 免費
- 8proe5.0野火版下載(中文版免費下載)
- 未知 | 138039次下載 | 免費
評論