- 對于計算機軟件的從業(yè)人員來說我們知道計算機有兩大核心處理器:
- CPU(Central Processing Unit)中央處理器:現(xiàn)代計算機的三大核心部分之一澎灸,作為整個系統(tǒng)的運算和控制單元茧彤。CPU 內(nèi)部的流水線結(jié)構(gòu)使其擁有一定程度的并行計算能力。其功能主要是解釋計算機指令以及處理計算機軟件中的數(shù)據(jù)祟蚀。CPU是計算機中負責讀取指令水援,對指令譯碼并執(zhí)行指令的核心部件。
- GPU(Graphics Processing Unit)圖形處理器:顧名思義GPU是一種可進行繪圖運算工作的專用微處理器宴杀。GPU 能夠生成 2D/3D 的圖形圖像和視頻癣朗,從而能夠支持基于窗口的操作系統(tǒng)、圖形用戶界面婴氮、視頻游戲斯棒、可視化圖像應用和視頻播放。GPU 具有非常強的并行計算能力主经。
- 對于視圖來說最終是呈現(xiàn)給用戶使用戶肉眼能夠看到荣暮,這里優(yōu)惠涉及到計算機的輸出設(shè)備
- 顯示器:以最經(jīng)典的CRT顯示器來說,顯示原理是通過CRT 的電子槍從上到下逐行掃描罩驻,每一次掃描發(fā)射電子束激發(fā)屏幕表面熒光粉點亮穗酥,來呈現(xiàn)一幀畫面。引入顯示器的概念主要是想引出像素點惠遏。
- 像素(Pixel):是顯示器顯示圖像的最小單位砾跃。以iPhone XS 為例它的像素是2436x1125,也就是有2436x1125 個小正方形像素點节吮。通過像素點的著色繪制抽高,手機屏幕上才能夠顯示不同的畫面。
- 位圖(bitmap): 亦稱為點陣圖像或柵格圖像透绩,是由像素點組成的翘骂。.png、.jpg圖片都是位圖的格式帚豪,而且是經(jīng)過壓縮的位圖
- CPU得到需要顯示的圖片后需要告知GPU碳竟,GPU處理完圖片后需要通知CPU
-
CPU和GPU的兩種架構(gòu)系統(tǒng)
左邊是分離性結(jié)構(gòu),CPU狸臣、GPU擁有各自的存儲系統(tǒng)莹桅,兩者通過PCI-e總線進行連接。這種結(jié)構(gòu)的缺點在于PCI-e相對于兩者具有低帶寬和高延遲烛亦,數(shù)據(jù)的傳輸成了其中的性情瓶頸诈泼。目前使用非常廣泛懂拾,如PC、智能手機等
右邊是耦合式結(jié)構(gòu)厂汗,CPU委粉、GPU共享內(nèi)存和緩存呜师。AMD的APU采用的就是此結(jié)構(gòu)娶桦,目前主要使用在游戲主機中,如PS4汁汗。
在存儲管理方面衷畦,分離式結(jié)構(gòu)中 CPU 和 GPU 各自擁有獨立的內(nèi)存,兩者共享一套虛擬地址空間知牌,必要時會進行內(nèi)存拷貝祈争。對于耦合式結(jié)構(gòu),GPU 沒有獨立的內(nèi)存角寸,與 GPU 共享系統(tǒng)內(nèi)存菩混,由 MMU 進行存儲管理。
圖形應用程序調(diào)用 OpenGL 或 Direct3D API 功能扁藕,將 GPU 作為協(xié)處理器使用沮峡。API 通過面向特殊 GPU 優(yōu)化的圖形設(shè)備驅(qū)動向 GPU 發(fā)送命令、程序亿柑、數(shù)據(jù)邢疙。 - CPU-GPU工作流
當CPU遇到圖像處理需求時,會調(diào)用GPU
該過程主要分為4步:
1. 將主存的處理數(shù)據(jù)復制到顯存中
2. CPU指令驅(qū)動GPU
3. GPU處理
4. GPU將顯存結(jié)果傳回主存
-
屏幕顯示圖像的原理
上邊已經(jīng)介紹過顯示器和像素的概念望薄,還是以CTR顯示器為例疟游,CTR電子槍從上到下逐行掃描,完成一幀畫面的展示痕支。當電子槍換行掃描時顯示器會發(fā)出一個水平同步信號(horizonal synchronization)颁虐,簡稱HSync;而當一幀畫面繪制完成后卧须,電子槍復位另绩,準備下一幀前,顯示器會發(fā)出一個垂直同步信號(vertical synchronization)故慈,簡稱VSync板熊。顯示器通常以固定的頻率進行刷新,這個刷新頻率是Vsync信號產(chǎn)生的頻率察绷。(在iOS上我們知道這個頻率是60fps,即1秒60次)干签。
CPU計算好顯示內(nèi)容的frame、頂點等信息提交給GPU拆撼,GPU渲染完成后將結(jié)果存入幀緩沖區(qū)容劳,視頻控制器會按照 VSync 信號逐幀讀取幀緩沖區(qū)的數(shù)據(jù)喘沿,經(jīng)過數(shù)據(jù)轉(zhuǎn)換后最終由顯示器進行顯示。
最簡單的情況下竭贩,幀緩沖區(qū)只有一個蚜印。此時,幀緩沖區(qū)的讀取和刷新都會有比較大的效率問題留量。為了解決效率問題窄赋,GPU 通常會引入兩個緩沖區(qū),即 雙緩沖機制(iOS中也采用的是雙緩存機制)楼熄。在這種情況下忆绰,GPU 會預先渲染一幀放入一個緩沖區(qū)中,用于視頻控制器的讀取可岂。當下一幀渲染完畢后错敢,GPU 會直接把視頻控制器的指針指向第二個緩沖器。
雙緩沖雖然能解決效率問題缕粹,但會引入一個新的問題稚茅。當視頻控制器還未讀取完成時,即屏幕內(nèi)容剛顯示一半時平斩,GPU 將新的一幀內(nèi)容提交到幀緩沖區(qū)并把兩個緩沖區(qū)進行交換后亚享,視頻控制器就會把新的一幀數(shù)據(jù)的下半段顯示到屏幕上,造成畫面撕裂現(xiàn)象双戳。為了解決這個問題虹蒋,GPU 通常有一個機制叫做垂直同步(簡寫也是 V-Sync),當開啟垂直同步后飒货,GPU 會等待顯示器的 VSync 信號發(fā)出后魄衅,才進行新的一幀渲染和緩沖區(qū)更新。這樣能解決畫面撕裂現(xiàn)象塘辅,也增加了畫面流暢度晃虫,但需要消費更多的計算資源,也會帶來部分延遲扣墩。
GPU對圖形數(shù)據(jù)的處理
- 通過OpenGL ES / Metal 的API CPU提交數(shù)據(jù)給GPU哲银,GPU內(nèi)部像流水線一樣處理所接收到的數(shù)據(jù),處理之后生成圖形渲染所需要的數(shù)據(jù)并存儲到幀緩存區(qū)呻惕。GPU的這個處理過程我們叫做GPU的圖形渲染管線
- 圖形渲染管線具體的可以分為六個階段
頂點著色器(Vertex Shader)
形狀裝備(Shape Assembly),又稱圖元裝配
幾何著色器(Geometry Shader)
光柵化(Rasterization)
片段著色器(Fragment Shader),又稱片元著色器
測試與混合(Tests and Blending)
在計算機中圖形都由圖元組成荆责,而在OpenGL和大多GPU處理工具中,圖元的類型只有三種:點亚脆、線做院、三角形,也就是說所有顯示到屏幕上的圖像都是由點、線或者三角形構(gòu)成的
頂點著色器:頂點著色器對每個頂點執(zhí)行一次運算键耕,它可以使用頂點數(shù)據(jù)來計算該頂點的坐標寺滚,顏色,光照屈雄,紋理坐標等村视,在渲染管線中每個頂點都是獨立地被執(zhí)行。
形狀(圖元)裝配:該階段將頂點著色器輸出的所有頂點作為輸入酒奶,并將所有的點裝配成指定圖元的形狀蚁孔。圖中則是一個三角形。圖元(Primitive) 用于表示如何渲染頂點數(shù)據(jù)讥蟆,如:點勒虾、線纺阔、三角形瘸彤。
以Metal為例,圖元裝配的類型也是點笛钝、線质况、三角形組成的:
typedef NS_ENUM(NSUInteger, MTLPrimitiveType) {
MTLPrimitiveTypePoint = 0,
MTLPrimitiveTypeLine = 1,
MTLPrimitiveTypeLineStrip = 2,
MTLPrimitiveTypeTriangle = 3,
MTLPrimitiveTypeTriangleStrip = 4,
} NS_ENUM_AVAILABLE(10_11, 8_0);
每個圖元由一個或者多個頂點組成,每個頂點定義一個點玻靡,一條邊的一端或者三角形的一個角结榄。每個頂點關(guān)聯(lián)一些數(shù)據(jù),這些數(shù)據(jù)包括頂點坐標囤捻,顏色臼朗,法向量以及紋理坐標等。所有這些頂點相關(guān)的信息就構(gòu)成頂點數(shù)據(jù)蝎土。
這里由于頂點數(shù)據(jù)較多视哑,因此性能更高的做法是,提前分配一塊顯存誊涯,將頂點數(shù)據(jù)預先傳入到顯存當中挡毅。這部分的顯存,就被稱為頂點緩沖區(qū)暴构。
另外跪呈,在繪制圖像時,總是會有一些頂點被多個圖元共享取逾,而反復對這個頂點進行運算常常是沒有必要的(也有某些特殊場景需要)耗绿。因此對通過索引數(shù)據(jù),指示OpenGL繪制頂點的順序砾隅,不但能防止頂點的重復運算误阻,也能在不修改頂點數(shù)據(jù)的情況下,一定程度的重新組合圖像。
和頂點數(shù)據(jù)一樣堕绩,索引數(shù)據(jù)也可以以索引數(shù)組的形式存儲在內(nèi)存當中策幼,調(diào)用繪制函數(shù)時傳入;或者提前分配一塊顯存奴紧,將索引數(shù)據(jù)存儲在這塊顯存當中特姐,這塊顯存就被稱為索引緩沖區(qū)。同樣的黍氮,使用緩沖區(qū)的方式唐含,性能一般會比直接使用索引數(shù)組的方式更加高效。
顯存沫浆,也被叫做幀緩存捷枯,它的作用是用來存儲顯卡芯片處理過或者即將提取的渲染數(shù)據(jù)。如同計算機的內(nèi)存一樣专执,顯存是用來存儲要處理的圖形信息的部件淮捆。
幾何著色器:該階段把圖元形式的一系列頂點的集合作為輸入,它可以通過產(chǎn)生新頂點構(gòu)造出新的(或是其它的)圖元來生成其他形狀本股。通俗來講:幾何著色器就是提供圖元相互之間的連接信息攀痊,將原本獨立的圖元連接起來。
注意:幾何著色器是一個可選的階段拄显,比如在圖元裝配階段苟径,已經(jīng)可以根據(jù)頂點坐標、索引值躬审、圖元類型(GL_QUADS)就可以確定圖形棘街,就無需再經(jīng)過幾何著色器這個階段。
光柵化:在光柵化階段承边,基本圖元被轉(zhuǎn)換為供片段著色器使用的片段(Fragment)遭殉,F(xiàn)ragment 表示可以被渲染到屏幕上的像素,它包含位置炒刁,顏色恩沽,紋理坐標等信息,這些值是由圖元的頂點信息進行插值計算得到的翔始。這些片元接著被送到片元著色器中處理罗心。這是從頂點數(shù)據(jù)到可渲染在顯示設(shè)備上的像素的質(zhì)變過程。
在片段著色器運行之前會執(zhí)行裁切(Clipping)城瞎。裁切會丟棄超出你的視圖以外的所有像素渤闷,用來提升執(zhí)行效率。
片段著色器:片段著色器的主要作用是計算每一個片段最終的顏色值脖镀。
可編程的片段著色器是實現(xiàn)一些高級特效如紋理貼圖飒箭,光照,環(huán)境光,陰影等功能的基礎(chǔ)弦蹂,這就是最精彩的部分肩碟。
在片段著色器之前的階段,渲染管線都只是在和頂點凸椿,圖元打交道削祈。而在 3D 圖形程序開發(fā)中,貼圖是最重要的部分脑漫,我們的 Resources髓抑,可以包含紋理等數(shù)據(jù),這些紋理可以被片段著色器使用优幸。片段著色器可以根據(jù)頂點著色器輸出的頂點紋理坐標對紋理進行采樣吨拍,以計算該片段的顏色值。從而調(diào)整成各種各樣不同的效果圖网杆。
測試與混合:
測試:在著色器程序完成之后羹饰,我們得到了像素數(shù)據(jù)。這些數(shù)據(jù)必須要通過測試才能最終繪制到畫布跛璧,也就是幀緩沖上的顏色附著上严里。
測試主要可以分為像素所有者測試(PixelOwnershipTest)、裁剪測試(ScissorTest)追城、模板測試(StencilTest)和深度測試(DepthTest),執(zhí)行的順序也是按照這個順序進行執(zhí)行燥撞。
最開始進行的測試是像素所有者測試座柱,主要是剔除不屬于當前程序的像素運算。
之后裁剪測試物舒,主要是剔除窗口區(qū)域之外的像素色洞。這兩個測試都是由OpenGL/Metal內(nèi)部實現(xiàn)的,無需開發(fā)者干預冠胯。
模板測試是通過模板測試程序去決定最終的像素是否丟棄火诸,同樣也是根據(jù)OpenGL / Metal的模板覆寫狀態(tài)決定是否更新像素的模板值。模板測試給開發(fā)者提供了高性能的裁剪方案荠察, 三維物體 的描邊技術(shù)置蜀,就是 模板測試 典型的用處之一。
深度測試悉盆,主要是通過對像素的運算出來的深度盯荤,也就是像素離屏幕的距離進行對比,根據(jù)OpenGL / Metal設(shè)定好的深度測試程序焕盟,決定是否最終渲染到畫布上秋秤。一般默認的程序是將離屏幕較近的像素保留,而將離屏幕較遠的像素丟棄。如果像素最終被渲染到畫布上灼卢,根據(jù)設(shè)定好的OpenGL / Metal深度覆寫狀態(tài)绍哎,可能會更新幀緩沖區(qū)上深度附著的值,方便進行下一次的比較鞋真。
混合:在 測試階段 之后蛇摸,如果像素依然沒有被剔除,那么 像素的顏色 將會和 幀緩沖區(qū) 中顏色附著上的顏色進行混合灿巧, 混合的算法可以通過 OpenGL/ Metal的函數(shù)進行指定赶袄。但是OpenGL/ Metal提供的混合算法是有限的,如果需要更加復雜的混合算法抠藕,一般可以通過像素著色器進行實現(xiàn)饿肺,當然性能會比原生的混合算法差一些。
抖動:在混合階段過后盾似,根據(jù)OpenGL/Metal的狀態(tài)設(shè)置敬辣,會決定是否有抖動這個階段。
抖動是一種針對對于可用顏色較少的系統(tǒng)零院,可以以犧牲分辨率為代價溉跃,通過顏色值的抖動來增加可用顏色數(shù)量的技術(shù)。抖動操作是和硬件相關(guān)的告抄,允許程序員所做的操作就只有打開或關(guān)閉抖動操作撰茎。實際上,若機器的分辨率已經(jīng)相當高打洼,激活抖動操作根本就沒有任何意義龄糊。默認情況下,抖動是激活的募疮。
經(jīng)過GPU圖形渲染管線處理后的數(shù)據(jù)會存放在幀緩沖區(qū)炫惩。然后視頻控制器會按照 VSync 信號逐幀讀取幀緩沖區(qū)的數(shù)據(jù),經(jīng)過數(shù)據(jù)轉(zhuǎn)換后最終由顯示器進行顯示阿浓。至此他嚷,一個圖形的渲染過程完成。