Android GPU渲染SurfaceFlinger合成RenderThread的dequeueBuffer/queueBuffer與fence機制(2)
?
計算fps幀率
用
adb shell dumpsys SurfaceFlinger --list
查詢當前的SurfaceView,然后有好多行,再把要查詢的行內容完整的傳給
adb shell dumpsys SurfaceFlinger --latency 窗口名
輸出一堆數字,第一行數字是當前的 VSYNC 間隔,單位納秒。如果屏幕是 60Hz ,就是 16.6ms,然后下面一堆數字,總共有 127 行,每一行有 3 個數字,每個數字都是時間戳,單位是納秒。
Android 顯示一幀大致分為幾個步驟
1,App 接收到 vsync-app 信號后開始工作。
2,App 主線程被Message喚醒,執行onVsync。
3,App 執行 doFrame ,處理input、animation、traversal、draw等。
4,App UIThread 跟RenderThread sync 數據。
5,App 執行DrawFrame,從SurfaceFlinger(后續簡稱SF) 的 BufferQueue 中 dequeueBuffer,取出一個bufffer后,執行渲染繪制,接著將繪制好的Buffer 通過queueBuffer 放回到BufferQueue中給 SF消費。
6,App queueBuffer 后, SF 中對應的 app buffer 會增加 +1。
7,Vsync-sf 到來后,SF 從BufferQueue 中 acquireBuffer一個Buffer 進行消費, 對應SF 中的 app buffer 會減 - 1 , SF 消費處理后,通過 releaseBuffer 將buffer 歸還到BufferQueue 中。
8,SF 通過 bind 跟 Hardware Composer HAL(HWC) 進行通信,通過一些處理后顯示到手機屏幕上。
dequeue(生產者發起) :
當生產者需要緩沖區時,它會通過調用 dequeueBuffer() 從 BufferQueue 請求一個可用的緩沖區,并指定緩沖區的寬度、高度、像素格式和使用標記。
queue(生產者發起):
生產者填充緩沖區并通過調用 queueBuffer() 將緩沖區返回到隊列。
acquire(消費者發起) :
消費者通過 acquireBuffer() 獲取該緩沖區并使用該緩沖區的內容。
release(消費者發起) :
當消費者操作完成后,它會通過調用 releaseBuffer() 將該緩沖區返回到隊列。
?
App 繪制的圖像內容是怎么最終顯示到手機屏幕?
App 要顯示的內容要繪制在 Buffer 里,這個 Buffer 是從 BufferQueue 通過 dequeueBuffer() 申請。申請到 Buffer 后,App 將內容填充到 Buffer ,通過 queueBuffer() 將 Buffer 還回去交給 SurfaceFlinger 去進行合成和顯示。然后,SurfaceFlinger 開始合成時候,調用 acquireBuffer() 從 BufferQueue 里面拿一個 Buffer 合成,合成完以后通過 releaseBuffer() 將 Buffer 還給 BufferQueue。
RenderThread 的 dequeueBuffer
dequeue 出隊,dequeueBuffer 就是從隊列中拿出一個 Buffer,這個隊列就是 SurfaceFlinger 中的 BufferQueue。app開始渲染前,首先需要通過 Binder 調用從 SurfaceFlinger 的 BufferQueue 中獲取一個 Buffer。
RenderThread 的 queueBuffer
queue 入隊,queueBuffer 是把?Buffer 放回到 BufferQueue,App 處理完 Buffer 后,會把這個 Buffer 通過 eglSwapBuffersWithDamageKHR -> queueBuffer ,將 Buffer 放回 BufferQueue。
上面流程有一個問題,在 App 繪制完通過 queueBuffer() 將 Buffer 還回時候,此時僅僅只是 CPU 側完成,GPU 實際上有沒有真正完成,CPU并不知道。因此如果此時GPU拿這個 Buffer 去合成/顯示,就會有問題(Buffer 可能還沒有完全繪制完)。由于 CPU 和 GPU 是異步的,因此CPU在代碼里執行一系列繪圖函數調用后,看上去函數已經返回,實際上,具體什么時候被GPU真正執行完畢 CPU 不知道,除非阻塞等待這些命令完全執行完,但這樣會帶來嚴重的性能問題,因為這樣使得 CPU 和 GPU 的并行完全喪失,CPU 會在 GPU 完成之前一直處于空等狀態。因此,需要一種機制,在不需要對 Buffer 進行讀寫時候,大家各干各的;當需要對 Buffer 進行讀寫時候,CPU可以知道此時 Buffer 在 GPU 的狀態,必要時候等一下。
fence 是這樣的同步機制——“柵欄”,把東西攔住。fence 要攔住什么東西呢?就是?Buffer。Buffer 在整個繪制、合成、顯示過程中,一直在 CPU,GPU 和 HWC 之間傳遞,某一方要使用 Buffer 前,需要檢查之前的使用者是否已經移交?Buffer 的“使用權”。而這里的“使用權”,就是 fence。當 fence 釋放(即 signal)時候,說明 Buffer 的上一個使用者已經交出了使用權,對于 Buffer 進行操作是安全的。
Android 總共有三類 fence —— acquire fence,release fence 和 present fence。
?acquire fence
? ? App 將 Buffer 通過 queueBuffer() 還給 BufferQueue 的時候,此時該 Buffer 的 GPU 側其實未必完成,此時會帶上一個 fence,這個 fence 就是 acquire fence。當 SurfaceFlinger/ HWC 要讀取 Buffer 以進行合成操作的時候,需要等 acquire fence 釋放之后才行。
?release fence
? ? 當 App 通過 dequeueBuffer() 從 BufferQueue 申請 Buffer,要對 Buffer 進行繪制時候,需要保證 HWC 已經不再需要這個 Buffer 了,即需要等 release fence signal 才能對 Buffer 進行寫操作。
?present fence
? ? 當前幀成功顯示到屏幕的時候,present fence 就會 signal。
每一個buffer都一個Fence狀態,代表這塊buffer是否還在被上一個使用者使用完,并且在轉移時都會攜帶當前Fence的fd,然后可以調用Fence的wait或者waitForever查詢Fence狀態,如果還在使用則等待,否則就可以使用。Fence按作用大體分兩種:acquireFence和releaseFence。前者用于生產者通知消費者生產已完成,后者用于消費者通知生產者消費已完成。
Fence保證GraphicBuffer在App, GPU和HWC三者間流轉時數據讀寫同步(不同進程 or 不同硬件間同步)。
從 SurfaceFlinger 的角度來看,App 部分主要負責生產 SurfaceFlinger 合成所需要的 Surface。
App 與 SurfaceFlinger 的交互主要集中在三點
1 Vsync 信號的接收和處理
2 RenderThread 的 dequeueBuffer
3 RenderThread 的 queueBuffer
?
從 dumpsys SurfaceFlinger --latency 獲取最新 127 幀的 present fence 的 signal time,當某幀 present fence 被 signal 時候,說明這一幀已經被顯示到屏幕上。因此,可以通過判斷1秒內有多少個 present fence signal ,反推出一秒內有多少幀被刷新(顯示)到屏幕上,從而計算出 fps。
統計一秒內?App 往屏幕刷了多少幀,在 Android 里,每一幀顯示到屏幕的標志是:present fence signal ,因此計算 App 的 fps 就可以轉換為:一秒內 App 的 Layer 有多少個有效 present fence signal 。
?
?
?
Android adb shell命令捕獲systemtrace_android 抓trace-CSDN博客文章瀏覽閱讀1.7k次,點贊2次,收藏5次。Android ADB調試真機設備Android ADB(Andorid Debug Bridge),是Android開發中有用的測試和調試工具。使用Android ADB調試設備,直接在Windows的dos命令窗口輸入命名adb即可,如圖:為什么執行adb命令后是這樣?Android ADB(Andorid Debug Bridge)調試真機設備_adb在線執行器_zhangphil的博客-CSDN博客。-t 時長,20s,20秒的trace文件。-o 保存文件路徑。_android 抓tracehttps://blog.csdn.net/zhangphil/article/details/131249820
Android GPU渲染屏幕繪制顯示基礎概念(1)-CSDN博客文章瀏覽閱讀696次,點贊20次,收藏12次。CPU返回后,會直接將GraphicBuffer提交給SurfaceFlinger,告訴SurfaceFlinger進行合成,但是這個時候GPU可能并未完成之前的圖像渲染,這時候就牽扯到一個同步,Android中,用的是Fence機制,SurfaceFlinger合成前會查詢Fence,如果GPU渲染沒有結束,則等待GPU渲染結束,GPU結束后,會通知SurfaceFlinger進行合成,SF合成后,提交顯示,最終完成圖像的渲染顯示。而對SF來說,只要有合成任務,它就得再去申請VSYNC-sf。https://blog.csdn.net/zhangphil/article/details/138585120Android性能:Double Buffer雙緩沖/Triple Buffer三緩沖丟幀Jank與無丟幀No Jank-CSDN博客文章瀏覽閱讀858次,點贊6次,收藏13次。Android ADB調試真機設備Android ADB(Andorid Debug Bridge),是Android開發中有用的測試和調試工具。使用Android ADB調試設備,直接在Windows的dos命令窗口輸入命名adb即可,如圖:為什么執行adb命令后是這樣?_android 抓trace。三Buffer輪轉情況下,基本不會有這種情況的發生,渲染線程一般在 dequeueBuffer 時,都可以順利拿到可用的 Buffer (如果 dequeueBuffer 本身耗時那就也會拉長時間)。
https://blog.csdn.net/zhangphil/article/details/138213964
?