tft每日頭條

 > 生活

 > opengl的性能

opengl的性能

生活 更新时间:2024-07-28 09:05:13
1.CPU與GPU

CPU内部組成:

opengl的性能(OpenGL--屏幕成像和渲染原理解析)1

GPU内部組成:

opengl的性能(OpenGL--屏幕成像和渲染原理解析)2

ALU:算術邏輯單元,是能實現多組算術運算和邏輯運算的組合邏輯電路。

CPU和GPU因為設計之初需求就不一樣,所以它們的組成不同,在計算機中的分工也不同。

可以看到,GPU有更多的ALU,而CPU有Control單元和Cache單元,普通的業務代碼因為邏輯複雜,數據類型複雜,跳轉複雜,依賴性高等,就更适合CPU來做。

而GPU不擅長處理這些複雜的邏輯,它更擅長處理單一的運算,大量的算術邏輯單元可以保證做到真正的高并發,所以大量的計算任務是适合它的工作,就比如GLSL代碼。

【更多音視頻學習資料,點擊下方鍊接免費領取↓↓,先碼住不迷路~】

C 程序員必看,抓住音視頻開發的大浪潮!沖擊年薪60萬

關于CPU和GPU的分工如下圖所示:

opengl的性能(OpenGL--屏幕成像和渲染原理解析)3

opengl的性能(OpenGL--屏幕成像和渲染原理解析)4

CPU更像管理者,負責調度和控制,也進行小量的計算,而GPU則是單純的打工人,負責大量的計算工作。

為了并行計算,每個計算單元都必須獨立。意味着所有數據必須沿一個方向流動,不可能檢查另一個計算單元的結果。GPU使計算單元一直處于忙碌狀态;一旦他們獲得自由,就會接收新的信息進行處理。一個計算單元不可能知道它在前一刻在做什麼。每個計算單元都是盲目且無記憶的。 -- 來自翻譯《The Book Of Shaders》

可以很明顯看到二者區别的是:

一個OpenGL程序,如果是跑在真機上,那毫無疑問是使用GPU運行的,非常流暢。如果是跑在模拟器上,是使用電腦的CPU在運行的,複雜的特效就會出現卡段。

擴展:Metal的使用就更極端,它必須使用真機運行,并且是6s及以上的真機。

2.計算機顯示方式演變

首先需要說明的是,計算機的顯示原理離不開視覺暫留現象。

視覺暫留: 人眼在觀察景物時,光信号傳入大腦神經,需經過一段短暫的時間,光的作用結束後,視覺形象并不立即消失,這種殘留的視覺稱“後像”,視覺的這一現象則被稱為“視覺暫留”。

物體在快速運動時, 當人眼所看到的影像消失後,人眼仍能繼續保留其影像0.1-0.4秒左右的圖像,所以當圖像的刷新幀率高于每秒16幀時,在人眼看來就是不間斷的顯示。

2.1 随機掃描顯示

随機掃描顯示是早期的顯示方式。CRT産生的電子束隻在屏幕上顯示圖形的部分移動,電子束逐條地跟蹤圖形的組成線條,從而生成線條圖。

這就決定了随機掃描顯示的刷新頻率依賴于顯示的線條數,和圖像的複雜度高度相關。圖形的定義是存放在稱為刷新顯示文件存儲區的一組畫線命令。

opengl的性能(OpenGL--屏幕成像和渲染原理解析)5

比如,圖1的每幀掃描成像時間就快于圖2。

當顯示的線條數很少時,則延遲每個刷新周期,以避免刷新速率超過每秒60幀。否則,線條的刷新速率過快,會燒壞熒光屏。

随機掃描顯示的優點在于作為一組畫線命令來存儲而非每個像素點的強度值,因而生成光滑的線條,而非有鋸齒的像素點。缺點是無法顯示逼真的有陰影的場景。

2.2 光栅掃描顯示

光栅掃描顯示是目前的主流。

在光栅掃描顯示中,電子束橫向掃描屏幕,一次一行,從頂到底依次進行。電子束在屏幕上逐點移動時,從被稱為幀緩存的存儲區取出每個像素點的強度值控制其顯示狀态。

這種實現原理決定了光栅掃描顯示的刷新頻率和圖像複雜度無關,刷新頻率可以是恒定的。

opengl的性能(OpenGL--屏幕成像和渲染原理解析)6

比如,圖1的每幀掃描成像時間就等于圖2。

光栅掃描顯示對屏幕上的每個點都有存儲強度信息的能力(除顔色信息外,其他的像素信息也存在幀緩存中),從而使得适用于包含陰影和彩色模式的逼真場景。

在某些光栅掃描系統中,采用了隔行掃描刷新的方式來顯示每一幀。第一次從頂到底掃描奇數行,第二次從頂到底掃描偶數行。隔行掃描使得掃描時間隻需要原先的一半就能看到屏幕的顯示。不過隔行掃描技術主要應用于較慢刷新頻率的場景。

【更多音視頻學習資料,點擊下方鍊接免費領取↓↓,先碼住不迷路~】

C 程序員必看,抓住音視頻開發的大浪潮!沖擊年薪60萬

2.4 光栅掃描顯示系統組成

光栅掃描系統除了使用CPU之外,還用視頻控制器來控制顯示設備的操作。

2.4.1 簡單光栅掃描顯示系統結構

opengl的性能(OpenGL--屏幕成像和渲染原理解析)7

簡單的光栅掃描系統如上圖所示。其中,幀緩存可以在系統存儲器中的任意位置,視頻控制器通過系統總線訪問幀緩存來刷新屏幕。

2.4.2 常用光栅掃描顯示系統結構

opengl的性能(OpenGL--屏幕成像和渲染原理解析)8

與簡單結構的相比,這個結構明顯提升了顯示效率,原因在于:

幀緩存使用了系統主存中的固定區域來存儲,且由視頻控制器直接訪問。

2.4.3 高級光栅顯示系統結構

opengl的性能(OpenGL--屏幕成像和渲染原理解析)9

高級的光栅顯示系統包含獨立的顯示處理器,也就是獨立顯卡。顯示處理器使CPU從圖形的複雜處理中解脫出來,還提供獨立的顯示處理器存儲區域。

2.4.4 視頻控制器的工作流程

無論何種結構,都存在視頻控制器,說明它是必不可少的。那它是如何工作的呢?

opengl的性能(OpenGL--屏幕成像和渲染原理解析)10

視頻控制器使用兩個寄存器來存放屏幕像素的坐标,而屏幕像素坐标和幀緩存的位置都使用笛卡爾坐标系。

開始時,将x寄存器置為0,将y寄存器置為頂部掃描行号。存儲在幀緩存中該像素對應位置的值被取出,并用來設置CRT電子束的強度值。然後,x寄存器加1,并沿該掃描線對每個像素重複執行。在處理完頂部掃描線的最後一個像素後,x寄存器複位為0,y寄存器減1,指向頂部掃描行的下一行。然後,沿該行依次掃描各像素,并且該過程對每條後繼的掃描線重複執行。當循環處理完底部掃描線的所有像素後,視頻控制器将寄存器複位為最高行掃描線上的第一個像素,刷新過程重複開始。

為了加速圖像處理,視頻控制器每次從刷新緩存中取出多個像素值。這些像素強度存放在單獨的像素寄存器中,用來為一組相鄰的像素控制CRT電子束的強度。當處理完改組像素後,從幀緩存取出下一塊像素值。

由于多數設備都提供多緩沖的機制,視頻控制器取像素強度值時還會在每個緩沖之間做切換。

2.4.5 總結

GPU的渲染流程大概如下:

GPU進行渲染時,會把數據先存儲在幀緩沖區裡,然後視頻控制器讀取幀緩沖區裡的數據,完成數模轉化,逐行掃描顯示畫面。

理論上,完美情況時,每掃描一張圖,就顯示一張,然後下一張也掃描完成等待刷新。

依次反複,屏幕就會保持流暢,那為什麼有些時候屏幕還會出現不流暢的現象,不流暢現象産生的原理是什麼?

【更多音視頻學習資料,點擊下方鍊接免費領取↓↓,先碼住不迷路~】

C 程序員必看,抓住音視頻開發的大浪潮!沖擊年薪60萬

3.撕裂與掉幀

opengl的性能(OpenGL--屏幕成像和渲染原理解析)11

畫面撕裂是比較影響用戶體驗的異常。畫面撕裂産生的原因如下:

當視頻控制器讀取讀取完一幀畫面顯示後,會去幀緩存讀取下一幀,如果幀緩存依然保持着上一幀的數據沒有被刷新,視頻控制器照常工作讀取幀緩存中的數據。當寄存器工作到某一行時,幀緩存的數據被更新為下一幀,視頻控制器就讀取到新的數據,而此時已經顯示的畫面是上一幀的數據,後續将要顯示的是下一幀的數據,撕裂也就産生了。

所以,撕裂的産生是因為幀緩存的刷新頻率沒有跟上屏幕的刷新頻率,根本原因就是CPU或GPU工作超時。

為了解決撕裂的問題,蘋果宣布iOS一直會使用垂直同步Vsync 雙緩沖的機制。

opengl的性能(OpenGL--屏幕成像和渲染原理解析)12

在VSync信号到來後,會在CPU中計算顯示内容,比如視圖的創建、布局計算、圖片解碼、文本繪制等。然後CPU會将計算好的數據提交到GPU,由GPU進行變換、合成、渲染。然後GPU會把渲染結果提交到幀緩存,等待下一次VSync信号到來時顯示到屏幕上。

由于垂直同步的機制,如果在一個VSync時間内,CPU或者GPU沒有完成内容提交,則那一幀就會被丢棄,等待下一次機會再顯示,而這時屏幕會刷新顯示上一幀的内容。

通過這種機制,就解決了撕裂的問題,但同時引入了新的問題 -- 掉幀。

當CPU或GPU渲染流⽔線耗時過⻓,前後顯示同一幀時,也就出現了掉幀現象(所以掉幀不是不渲染數據,而是重複渲染同一幀數據)。

至于掉幀無法被完全解決,因為CPU或GPU的工作是不可預估的。隻能盡量合理的使用CPU或GPU減少掉幀次數。

這裡引入三緩沖機制的概念:

開辟三個幀緩沖區,盡可能保證總有個緩沖區中有下一幀需要的内容。不過這也是治标不治本的手段。

總結:

撕裂是由于CPU或GPU耗時過⻓而産生的,iOS解決的方式是引入垂直同步Vsync 雙緩沖的機制,而解決撕裂是以掉幀作為代價的,掉幀不能完全被解決。

4.iOS下的渲染框架和流程

opengl的性能(OpenGL--屏幕成像和渲染原理解析)13

App通過調用Core Graphics、Core Animation、Core Image等框架的接口觸發圖形渲染,這些框架在通過 OpenGL/Metal 來調用GPU進行繪制,最終将内容顯示到屏幕之上.

當然,APP也能直接使用OpenGL/Metal提供的接口進行繪制。

總結:

  1. UIKit:通過UIKit提供的街交口進行布局和繪制界面,UIKit本身不具備顯示能力,是通過底層的layer實現的。
  2. CoreAnimation:本質上是一個複合引擎,主要職責在于渲染,構建和動畫。CAlayer屬于CoreAnimation,是界面可視化的承載。
  3. CoreGraphics:基于Quartz的高級繪圖引擎,提供了輕量級的2d渲染能力,主要是用于運行時繪圖的。CG開頭的類都屬于CoreGraphics。
  4. CoreImage:一個高性能的圖像處理分析的框架,運行前繪制圖形,主要提供圖形的濾鏡功能。
  5. OpenGL ES:針對嵌入式設備,是OpenGL的子集。直接操作硬件服務,是跨平台的。
  6. Metal:蘋果自研的針對自家設備的圖形渲染标準,在蘋果設備上性能最優。
5.CPU和GPU的渲染流水線

opengl的性能(OpenGL--屏幕成像和渲染原理解析)14

總的來說,圖形的渲染分為兩個部分:CPU部分,GPU部分

在CPU部分主要做了3步操作:

1.Handle Event 接收事件,包括點擊事件,布局的改變等。

2.Commit transcation 提交事務,通過CPU完成顯示内容的計算,然後對圖層樹進行打包,在下一個runloop時提交到Render server進程

3.Render Server 将收到的包進行解碼,處理完數據後,再傳遞至 GPU

需要注意的是,app本身的進程并不負責渲染,渲染是由一個獨立的進程負責,就是Render Server進程

在GPU部分主要就是渲染管線的内容:

這部分的内容在OpenGL初探 - 專有名詞解析中的最後總結已說明。

最後,GPU的渲染管線結束後,需要在等下一個runloop來時顯示幀緩沖區内的内容。

以上渲染流水線舉個具體的例子如下:

如果一張圖片被設置為imageview的屬性時會發生什麼?

首先,CATransaction捕獲到圖層樹的變化,在下一個runloop周期到來時,Core Animation會提交這個隐式動畫,會對圖片做以下操作:

  • 分配内存緩沖區用于管理文件IO和解壓縮操作
  • 将文件從磁盤讀到内存
  • 将壓縮的圖片數據解壓成未壓縮的位圖數據,這一步操作比較耗時,且在主線程
  • CPU計算好frame等數據,對圖片解壓後,交給GPU做圖片渲染
  • Calayer使用原始數據進行繪制Content

OpenGL或者shader的編程都是面向過程的,大部分是面向GPU的,這和面向CPU編程的思想是有所不同的。以前總覺得圖形的變換總是在第一幀的基礎上進行是費時費力的,如果在上一幀的基礎上變換豈不是更省事,理解了屏幕成像和渲染原理之後對這個問題,或者說對圖形學才有了初步的理解。

如果你對音視頻開發感興趣,覺得文章對您有幫助,别忘了點贊、收藏哦!或者對本文的一些闡述有自己的看法,有任何問題,歡迎在下方評論區讨論!

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved