CPU
內部組成:web
GPU
內部組成:編程
ALU
:算術邏輯單元
,是能實現多組算術運算和邏輯運算的組合邏輯電路。緩存
CPU
和GPU
由於設計之初需求就不同,因此它們的組成不一樣,在計算機中的分工也不一樣。markdown
能夠看到,GPU
有更多的ALU
,而CPU
有Control
單元和Cache
單元,普通的業務代碼由於邏輯複雜,數據類型複雜,跳轉複雜,依賴性高等,就更適合CPU
來作。併發
而GPU
不擅長處理這些複雜的邏輯,它更擅長處理單一的運算,大量的算術邏輯單元能夠保證作到真正的高併發,因此大量的計算任務是適合它的工做,就好比GLSL
代碼。app
關於CPU
和GPU
的分工以下圖所示:框架
CPU
更像管理者,負責調度和控制,也進行小量的計算,而GPU
則是單純的打工人,負責大量的計算工做。高併發
爲了並行計算,每一個計算單元都必須獨立。意味着全部數據必須沿一個方向流動,不可能檢查另外一個計算單元的結果。
GPU
使計算單元一直處於忙碌狀態;一旦他們得到自由,就會接收新的信息進行處理。一個計算單元不可能知道它在前一刻在作什麼。每一個計算單元都是盲目且無記憶的。 -- 來自翻譯《The Book Of Shaders》
oop
能夠很明顯看到兩者區別的是:佈局
一個
OpenGL
程序,若是是跑在真機上,那毫無疑問是使用GPU
運行的,很是流暢。若是是跑在模擬器上,是使用電腦的CPU
在運行的,複雜的特效就會出現卡段。
擴展:
Metal
的使用就更極端,它必須使用真機運行,而且是6s
及以上的真機。
首先須要說明的是,計算機的顯示原理離不開視覺暫留
現象。
視覺暫留
: 人眼在觀察景物時,光信號傳入大腦神經,需通過一段短暫的時間,光的做用結束後,視覺形象並不當即消失,這種殘留的視覺稱「後像」,視覺的這一現象則被稱爲「視覺暫留」。
物體在快速運動時, 當人眼所看到的影像消失後,人眼仍能繼續保留其影像0.1-0.4秒
左右的圖像,因此當圖像的刷新幀率高於每秒16幀
時,在人眼看來就是不間斷的顯示。
隨機掃描顯示
是早期的顯示方式。CRT
產生的電子束只在屏幕上顯示圖形的部分移動,電子束逐條地跟蹤圖形的組成線條,從而生成線條圖。
這就決定了隨機掃描顯示
的刷新頻率依賴於顯示的線條數,和圖像的複雜度高度相關。圖形的定義是存放在稱爲刷新顯示文件
存儲區的一組畫線命令。
好比,圖1
的每幀掃描成像時間就快於圖2
。
當顯示的線條數不多時,則延遲每一個刷新週期,以免刷新速率超過每秒60幀。不然,線條的刷新速率過快,會燒壞熒光屏。
隨機掃描顯示
的優勢在於做爲一組畫線命令來存儲而非每一個像素點的強度值,於是生成光滑的線條,而非有鋸齒的像素點。缺點是沒法顯示逼真的有陰影的場景。
光柵掃描顯示
是目前的主流。
在光柵掃描顯示
中,電子束橫向掃描屏幕,一次一行,從頂到底依次進行。電子束在屏幕上逐點移動時,從被稱爲幀緩存
的存儲區取出每一個像素點的強度值控制其顯示狀態。
這種實現原理決定了光柵掃描顯示
的刷新頻率和圖像複雜度無關,刷新頻率能夠是恆定的。
好比,圖1
的每幀掃描成像時間就等於圖2
。
光柵掃描顯示
對屏幕上的每一個點都有存儲強度信息的能力(除顏色信息外,其餘的像素信息也存在幀緩存中),從而使得適用於包含陰影和彩色模式的逼真場景。
在某些光柵掃描系統中,採用了隔行掃描
刷新的方式來顯示每一幀。第一次從頂到底掃描奇數行,第二次從頂到底掃描偶數行。隔行掃描
使得掃描時間只須要原先的一半就能看到屏幕的顯示。不過隔行掃描
技術主要應用於較慢刷新頻率的場景。
光柵掃描系統除了使用CPU以外,還用視頻控制器
來控制顯示設備的操做。
簡單的光柵掃描系統如上圖所示。其中,幀緩存
能夠在系統存儲器中的任意位置,視頻控制器
經過系統總線訪問幀緩存
來刷新屏幕。
與簡單結構的相比,這個結構明顯提高了顯示效率,緣由在於:
幀緩存
使用了系統主存中的固定區域來存儲,且由視頻控制器
直接訪問。
高級的光柵顯示系統包含獨立的顯示處理器,也就是獨立顯卡
。顯示處理器使CPU從圖形的複雜處理中解脫出來,還提供獨立的顯示處理器存儲區域。
不管何種結構,都存在視頻控制器
,說明它是必不可少的。那它是如何工做的呢?
視頻控制器
使用兩個寄存器來存放屏幕像素的座標,而屏幕像素座標和幀緩存的位置都使用笛卡爾座標系
。
開始時,將x寄存器
置爲0,將y寄存器
置爲頂部掃描行號。存儲在幀緩存
中該像素對應位置的值被取出,並用來設置CRT
電子束的強度值。而後,x寄存器
加1,並沿該掃描線對每一個像素重複執行。在處理完頂部掃描線的最後一個像素後,x寄存器
復位爲0,y寄存器
減1,指向頂部掃描行的下一行。而後,沿該行依次掃描各像素,而且該過程對每條後繼的掃描線重複執行。當循環處理完底部掃描線的全部像素後,視頻控制器
將寄存器
復位爲最高行掃描線上的第一個像素,刷新過程重複開始。
爲了加速圖像處理,視頻控制器
每次從刷新緩存中取出多個像素值。這些像素強度存放在單獨的像素寄存器
中,用來爲一組相鄰的像素控制CRT
電子束的強度。當處理完改組像素後,從幀緩存
取出下一塊像素值。
因爲多數設備都提供多緩衝的機制,視頻控制器
取像素強度值時還會在每一個緩衝之間作切換。
GPU
的渲染流程大概以下:
GPU
進行渲染時,會把數據先存儲在幀緩衝區裏,而後視頻控制器讀取幀緩衝區裏的數據,完成數模轉化,逐行掃描顯示畫面。
理論上,完美狀況時,每掃描一張圖,就顯示一張,而後下一張也掃描完成等待刷新。
依次反覆,屏幕就會保持流暢,那爲何有些時候屏幕還會出現不流暢的現象,不流暢現象產生的原理是什麼?
畫面撕裂是比較影響用戶體驗的異常。畫面撕裂產生的緣由以下:
當
視頻控制器
讀取讀取完一幀畫面顯示後,會去幀緩存
讀取下一幀,若是幀緩存
依然保持着上一幀的數據沒有被刷新,視頻控制器
照常工做讀取幀緩存中的數據。當寄存器工做到某一行時,幀緩存
的數據被更新爲下一幀,視頻控制器
就讀取到新的數據,而此時已經顯示的畫面是上一幀的數據,後續將要顯示的是下一幀的數據,撕裂
也就產生了。
因此,撕裂的產生是由於幀緩存
的刷新頻率沒有跟上屏幕的刷新頻率,根本緣由就是CPU
或GPU
工做超時。
爲了解決撕裂
的問題,蘋果宣佈iOS
一直會使用垂直同步Vsync + 雙緩衝的機制
。
在VSync
信號到來後,會在CPU
中計算顯示內容,好比視圖的建立、佈局計算、圖片解碼、文本繪製等。而後CPU
會將計算好的數據提交到GPU
,由GPU
進行變換、合成、渲染。而後GPU
會把渲染結果提交到幀緩存,等待下一次VSync
信號到來時顯示到屏幕上。
因爲垂直同步的機制,若是在一個VSync
時間內,CPU
或者GPU
沒有完成內容提交,則那一幀就會被丟棄,等待下一次機會再顯示,而這時屏幕會刷新顯示上一幀的內容。
經過這種機制,就解決了撕裂
的問題,但同時引入了新的問題 -- 掉幀
。
當CPU
或GPU
渲染流⽔線耗時過⻓,先後顯示同一幀時,也就出現了掉幀
現象(因此掉幀
不是不渲染數據,而是重複渲染同一幀數據)。
至於掉幀沒法被徹底解決,由於CPU
或GPU
的工做是不可預估的。只能儘可能合理的使用CPU
或GPU
減小掉幀次數。
這裏引入三緩衝機制
的概念:
開闢三個幀緩衝區,儘量保證總有個緩衝區中有下一幀須要的內容。不過這也是治標不治本的手段。
總結:
撕裂
是因爲CPU
或GPU
耗時過⻓而產生的,iOS
解決的方式是引入垂直同步Vsync + 雙緩衝的機制
,而解決撕裂
是以掉幀
做爲代價的,掉幀
不能徹底被解決。
App
經過調用Core Graphics
、Core Animation
、Core Image
等框架的接口觸發圖形渲染,這些框架在經過 OpenGL/Metal
來調用GPU
進行繪製,最終將內容顯示到屏幕之上.
固然,APP
也能直接使用OpenGL/Metal
提供的接口進行繪製。
總結:
UIKit
:經過UIKit
提供的街交口進行佈局和繪製界面,UIKit
自己不具有顯示能力,是經過底層的layer
實現的。
CoreAnimation
:本質上是一個複合引擎,主要職責在於渲染,構建和動畫。CAlayer
屬於CoreAnimation
,是界面可視化的承載。
CoreGraphics
:基於Quartz
的高級繪圖引擎,提供了輕量級的2d
渲染能力,主要是用於運行時繪圖的。CG
開頭的類都屬於CoreGraphics
。
CoreImage
:一個高性能的圖像處理分析的框架,運行前繪製圖形,主要提供圖形的濾鏡功能。
OpenGL ES
:針對嵌入式設備,是OpenGL
的子集。直接操做硬件服務,是跨平臺的。
Metal
:蘋果自研的針對自家設備的圖形渲染標準,在蘋果設備上性能最優。
總的來講,圖形的渲染分爲兩個部分: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
編程的思想是有所不一樣的。之前總以爲圖形的變換老是在第一幀的基礎上進行是費時費力的,若是在上一幀的基礎上變換豈不是更省事,理解了屏幕成像和渲染原理
以後對這個問題,或者說對圖形學
纔有了初步的理解。