PowerVR性能建議-黃金法則


PowerVR性能建議-黃金法則

2021-03-02想像力技術

來源:知乎

作者:topameng

本文檔覆蓋了開發人員需要遵循的主要原則,以避免圖形應用程式產生嚴重的性能問題。這些建議來自PowerVR技術支持團隊。注意,不同GPU,不同驅動,具有不同的性能特徵。性能優化應該是一個不斷分析profiling和實驗的過程。儘可能多地了解目標平台的信息,以便理解不同的圖形架構,以儘可能有效的方式使用設備。

可以在設備製造商的網站查找規範,包括可用的社區開發資源。PowerVR Graphics SDK提供的公開架構和性能建議文檔供參考如下:

開發人員的PowerVR硬件架構概述

針對開發人員的PowerVR Series5體系結構指南

PowerVR性能建議

PowerVR低層GLSL優化

PowerVR指令集參考IMR(Immediate Mode Rendering) 立即渲染IMR:是將一個圖元(通常是三角形),從頭到尾走完整個管線Pipeline,中間不會停止。這種結構,控制簡單,容易實現。但在做blending的時候需要從存儲單元(顯存)中回讀之前渲染的結果(framebuffer)。寫入每一個像素時需要讀取depth/stencil緩衝區,不透明像素還需要寫入depth/stencil緩衝區。而且渲染按照提交順序直接執行,可能造成不可見物體也進行了渲染,造成overdraw浪費帶寬和計算。可想而知在繪製一個複雜的大場景時帶寬消耗是比較大的。桌面GPU採用這個架構。是因爲獨立桌面GPU都有顯存的,不需要通過系統總線從系統內存中讀回數據。所以帶寬開銷比較小,是可以接受的。這些年GPU算力增長迅速, 而帶寬增長緩慢,隨著4K普及,桌面GPU帶寬壓力也在增大。也逐步產生了了一些基於tile的新渲染算法,如Forward+, tiled deferred lighting等,這裡不做詳述。對於移動端的處理器(基本可以認爲是ARM處理器)使用統一的內存存儲空間尋址,這樣讀取depth/stencil緩衝區以及回讀像素到GPU進行blending就變成了一件非常奢侈的事情。它會嚴重占用系統帶寬,造成功耗提升,而且會影響整個系統晶片SOC的處理能力。TBR(Tile Based Rendering)基於Tile的渲染爲了減少這種巨大的帶寬需求。大部分移動GPU使用基於tile的渲染。將幀緩衝區framebuffer(包括深度緩衝區,多重採樣緩衝區等)從內存移到高速片上on-chip緩存中。因爲是片上的,更接近計算發生的地方(gpu晶片),訪問它需要的功耗更少。但不幸的是,片上cache大小有限。通常片上tile緩衝區大小由GPU決定(通常32×32像素, 也可以小到16 x 16像素)。一旦完成tile的渲染,拷貝它到更耗電的主內存,僅僅需要回寫最小的結果集合(顏色值):不需要寫depth/stencil值。depth/stencil測試和(顏色)blending混合是完全在片上進行的。TBR不再以圖元primitive爲單位,不像IMR那樣執行完頂點著色器後立刻執行片段著色器。而是以rendertarget爲單位,在一個rendertarget處理過程中,把所有提交的圖元執行完頂點著色器之後,寫回主內存,再進行光柵化,之後再執行片段著色器。我們將這些收集的中間數據稱爲frame data。一般這些數據的讀取和寫入使用的帶寬比tile節省的帶寬小的多。如果三角形數量超多會導致frame data膨脹,以及複雜的頂點shader, 都會抵消tile GPU的優勢。儘管相對IMR,TBR架構節省了帶寬,但它並沒有在渲染上減少overdraw。當渲染每個tile時,按照提交順序處理幾何體,如果一個不可見物體順序靠前,幾何體數據就會被處理,並且產生片段fragment,並爲之提取紋理數據(浪費帶寬),執行片段著色(浪費計算)。所以爲了更好的利用Eayly-Z技術減少overdraw。應用程式需要從前到後排序不透明幾何體再提交。讓更靠近攝像機的不透明物體優先渲染。大部分安卓屬於TBR架構,但Mail上有Forward Pixel Kill(正向像素剔除)技術可以將通過early-z未進行片段渲染之前的像素剔除掉。當然安卓上還有Adreno,它處理overdraw最差。所以unity在安卓上對排序不透明物體也進行了排序TBDR(Tile-Based Deferred Rendering)基於tile的延遲渲染TBDR架構實現了TBR不具備的提交順序無關的像素級隱藏面消除功能。HSR通過使用Tag Buffer跟蹤可視的片段及其所屬的圖元,來高效消除不透明物體渲染的overdraw。也減少硬體提取片段著色所需數據(包括紋理數據和中間緩衝數據intermediate buffer data)浪費的系統內存帶寬。因爲在HSR階段只從frame data提取*1 position數據。其他幾何體數據延遲到管線的*2階段提取,所以也節省了中間緩衝數據消耗的帶寬。負責逐tile隱藏面消除功能模塊稱爲ISP(圖像合成處理器Image Synthesis Processor)TSP(Texture and Shading Processor紋理和著色處理器)。ISP 按tile逐個處理顯示列表中的所有三角形。計算三角形方程。如果啓動了深度測試,爲tile上圖元覆蓋的每個片段獲取深度信息,將計算的深度信息與tile片上深度緩衝區記錄的值對比來決定片段是否可見。可見則更新片上深度緩衝區和tag buffer(tag buffer記錄。直到處理完所有三角形,ISP 按組向TSP提交屬於同一圖元的片段,這樣同時處理的片段屬於同一圖元。可以提升硬體的cache命中率。而本文主要針對PowerVR TBDR架構做性能建議。在完全理解了圖形架構之後,了解其他因素也很重要,例如CPU處理能力,內存帶寬和溫度負荷也會影響應用程式的性能。

2. 對應用程式進行分析Profiler

在嘗試優化應用程式之前,了解性能瓶頸的位置非常重要。這樣可以確保不浪費精力,也不會犧牲視覺質量以獲得最小的收益。如果針對非性能瓶頸區域不適當地執行優化,則可能不會有性能提升。在某些情況下,錯誤的優化可能會導致性能下降。從PowerVR開發技術團隊的經驗來看,我們得出以下常見瓶頸列表,這些瓶頸通常存在於未經優化的應用程式中,從常見到不常見排序:

CPU佔用率

帶寬使用率

CPU/GPU同步

片段著色器指令

幾何體上傳

紋理上傳

頂點著色器指令

在此過程中,分析工具至關重要,方便開發人員了解應用程式正在發生的事情,運行的硬體以及瓶頸的發生方式和位置。可以使用分析工具PVRTrace和PVRTune

3. 不要使用不必要的Alpha Blend

確保在必要時才使用Alpha Blending,(減少Alpha Blending才能)充分利用硬體延遲架構並節省帶寬。儘可能關閉alpha blending, 如果需要透明對象,儘量將透明對象數量保持最小。這背後的原因是延遲渲染器(如PowerVR圖形核心)在調用片段著色器處理片段之前,先計算片段的可見性。這樣可以防止不可見片段被(不必要地)處理並輸出到圖像。如果開啓了alpha blending, 則用於確定片段可見性的硬體HSR將無法使用。這是因爲被alpha-blend片段遮擋的片段可能會影響最終的渲染圖像。因爲這種行爲,啓動alpha blending消除了延遲渲染圖形架構的好處。這意味著硬體不再能夠決定片段的可見性並將其(不可見的片段)從管線中刪除。這可能會導致過度繪製overdraw(即正在處理的片段在最終圖像上實際不可見)。overdraw會對應用程式性能產生負面影響,特別是處於渲染瓶頸的應用程式。在立即模式GPU上,混合Blending通常比較昂貴,因爲它需要在幀緩衝區framebuffer上完成一個讀取-修改-寫入的循環。而幀緩衝區framebuffer保存在相對較慢的內存中。在基於tile的GPU上,這個讀取-修改-寫入循環完全在片上完成,因此消耗非常小。一些GPU擁有專用的Blending硬體,這讓混合操作變得基本上免費。之上所述的性能耗費,主要指Alpha blending帶來的影響,而不是指像素上的alpha操作。

4. 執行Clear

在基於tile的圖形架構上,清除幀緩衝區的內容,可以避免取回前一幀的frame data,從而減少內存帶寬。訪問系統內存比其他圖形操作耗費更多的帶寬,帶來更大的功耗。將內存訪問保持在最低限度,可以降低應用程式產生內存帶寬瓶頸的機率,並且可以降低應用程式的功耗。大多數應用程式需要在渲染結束時生成圖像,但不需要在幀之間保留深度和模板數據。如果不需要在渲染結束時保留幀緩衝區附件framebuffer attachments,則可以使相應的幀緩衝附件無效,防止它們被寫入系統內存。在新一幀開始時,很少有應用程式需要保留之前顏色緩衝區的內容。因此,如果不需要之前的幀緩衝器的內容。在渲染開始時通過清除操作,避免驅動程序將它們從系統內存加載到片上tile內存中。執行清除並且廢棄幀緩衝區的最終結果是:大幅減少系統內存帶寬占用並降低功耗。在OpenGL ES中,當渲染開始時,通過調用glClear函數來執行清除操作。另外,在渲染結束時,glDiscardFramebufferEXT或glInvalidateFramebuffer函數可用於廢棄幀緩衝區。Vulkan API可以顯式控制幀緩衝區附件的加載和存儲操作。在創建幀緩衝區時,將加載操作設置爲VK_ATTACHMENT_LOAD_OP_DONT_CARE 或者 VK_ATTACHMENT_LOAD_OP_CLEAR。儲操作設置爲VK_ATTACHMENT_STORE_OP_DONT_CARE,除非要保留數據。

5. 不要在幀中間更新數據緩衝區

修改GPU當前使用的(in-flight)資源(例如頂點緩衝區和紋理)有顯著的成本。移動圖形處理器往往有一幀的延遲latency,以確保硬體能夠被充分利用。因此,更改未完成的渲染所需資源,通常會導致執行一下操作:

由於紋理通常在片段著色期間訪問,在圖形管線中比訪問頂點屬性更晚,因此紋理修改(導致圖形驅動程序掛起的)成本高於修改頂點緩衝區。爲了性能,驅動程序可以選擇通過創建臨時緩衝區(例如ghosting)來避免掛起stall。但對於緩衝區存儲空間用完的應用程式,無法這麼做。對於不同的GPU和驅動程序,圖形處理器採用掛起stalling還是ghosting也會有變化。爲了獲得最佳性能,僅在絕對必要時修改頂點緩衝區和紋理。如果必須修改緩衝區,可以在應用程式端使用循環緩衝區,這樣當圖形處理器可以讀取一個緩衝區對象時,應用程式CPU線程也可以同時寫入另一個。這樣就可以防止stalling和ghosting行爲。如果應用程式使用Vulkan 圖形API, 那麼應用程式開發人員有責任同步圖形處理器。適當的機制如放置柵欄fences或者信號semaphores,以確保應用程式在圖形處理器使用資源時不能訪問它。這樣可以更好的控制訪問資源的方式和時間,但代價是更複雜的應用程式,因爲驅動不能防範當前圖形處理器使用的數據被訪問。

6. 使用壓縮紋理

在某些情況下,需要考慮紋理大小和紋理壓縮之間的平衡。可以使用更大的紋理和低比特率壓縮方案,來實現帶寬節省和可接受的圖像質量之間的更好平衡。不要與圖像文件壓縮混淆,紋理壓縮目的是:減少運行時紋理占用的內存。這提供了幾個性能優勢,主要是減少了發送數據到圖形核心系統時消耗的系統內存帶寬。PVRTC和PVRTCII是PowerVR專有的壓縮技術,在(PowerVR)硬體上能夠獲得最佳的性能,平均每個像素占用2個比特。壓縮紋理的紋理緩存也很高效,因爲較低的像素大小,允許更多的像素放入到有限大小的紋理單元緩存cache中(紋理單元並不是讀取一個像素點,通常是一個塊chunk)。對於PowerVR系列和圖形目標,某些會支持額外的壓縮紋理格式,如ASTC。

7. 使用mipmaping

這樣能夠提升紋理緩存效率,從而減少帶寬占用提升性能Mipmaps是紋理圖像更小的預過濾變體,代表紋理的不同細節層次lod。使用mipmaps時,通過使用縮小過濾模式,圖形核心可以設置爲自動計算最接近細節層次,映射該mipmap的紋素到渲染目標像素pixels上。這意味著能夠使用正確的mipmap來進行紋理映射

使用mipmap有兩個重要的優點:

mipmapping的唯一限制是需要大約每個圖像多付出三分之一的紋理內存。根據具體情況,與渲染速度和圖像質量相比,此成本可能較小。

有一些情況例外,應該避免使用mipmaps。例如:

理想情況下,應使用像PVRTexTool這樣的工具來離線創建mipmap, PVRTexTool作爲PowerVR Graphics SDK一部分提供。也可以實時產生mipmap,這對於渲染到紋理目標時更新mipmaps十分有用。在Opengl ES中,可以使用glGenerateMipmap函數實現。在Vulkan中沒有這樣的內置函數,開發人員必須手動生成mipmaps。對於壓縮紋理不能在線生成mipmaps。如PVRTC必須離線生成mipmaps。必須考慮哪一個成本更合適:離線生成的存儲成本,還是運行時生成mipmaps的運行時成本(以及在Vulkan情況下,增加的代碼複雜性)

8. 不要使用Discard

避免在紋理階段進行深度測試處理,因爲在early-z架構上這會降低性能。應用程式應避免在片段著色器中使用discard操作,因爲使用它不會提升性能(如果丟棄區域很大,在pc上可以起到優化作用)。因爲大部分移動圖形核心使用基於tile的延遲渲染(TBDR)架構,使用discard會抵消這類架構的優點。應用程式應避免alpha test,與不透明圖元不同,alpha test圖元,在early depth testing(如PowerVR的隱藏面消除hsr,被更靠近攝像機片段遮擋的片段會被丟棄)管線階段不能執行深度寫入。直到片段著色器執行並且片段可見性已知之前,alpha test圖元都不能將深度數據寫入到深度緩衝區中。這些延遲的深度寫入會影響性能,因爲直到alpha test圖元更新深度緩衝區,後續圖元都不能被處理。

爲了獲得最佳性能,考慮使用alpha blending替代alpha test來避免延遲深度寫入操作。爲了確保HSR儘可能移除更多的overdraw,需要按如下順序提交繪製:

不透明opaque

經過Alpha測試

粗略情況,可以使用alpha blend並設置alpha爲0代替discard操作。還需要對透明物體從前到後排序。注意alpha test物體一般是不需要排序的。因爲dicard操作只發生在alpha小於閾值的像素上,這部分像素會因alpha blend受益,但如果大部分像素是作爲不透明渲染的,這部分並不能受益反倒可能因overdraw而損失性能。而且很多時候因爲透明排序問題導致無法簡單替換。如果保證渲染完全正確,就不能簡單使用alpha blending替換alpha test,需要使用Z-Prepass渲染策略。首先使用包含discard邏輯的簡單片段著色器(不包含光照計算等)來填充深度緩衝區,然後再次渲染場景,設置深度測試函數爲GL_EQUAL,使用包含光照的shader來渲染,雖然多pass渲染會導致性能下降,但這種方法比單pass包含大量計算和discard操作的渲染方式性能更好。如果渲染瓶頸在discard操作上可以採取Z-Prepass這種方式,但一般引擎是不會做設個假設的,對於TBDR移動架構也並不推薦Z-prepass(見後面對depth pre-pass的說明)。如果discard像素過多,也可以通過增加少量三角形減少需要discard區域(alpha值小於閾值區域)來優化,當然有時只是改變三角形形狀就能達到縮小discard區域目的。

9. 不要強制不必要的同步

避免可能掛起stall圖形管線的API功能,並且不要直接訪問硬體緩衝區。當CPU和圖形核心任務並行運行時,圖形應用程式可達到最佳性能。當一幀frame頂點處理任務與前一幀frame的片段著色任務並行時,圖形核心也會最有效地運行。當應用程式發布導致圖形核心中斷的命令時,會顯著的降低性能。

硬體調度任務最有效方式是保持頂點處理和片段任務能夠並行。爲了實現這一點,應用程式目標是儘可能移除導致CPu和圖形核心同步的函數:

應用程式性能不佳的常見原因之一是:應用程式從CPU訪問幀緩衝區內容。當發布這樣的操作時,應用程式發起該調用的CPU線程會被掛起直到圖形核心完成該幀緩衝區附件的渲染。當渲染完成之後,CPU才能開始從附件讀取數據。在這期間,圖形核心沒有寫入該附件的權限,這可能導致圖形核心掛起stall對該幀緩衝區的後續渲染。由於成本高昂,這些操作應該在絕對必要時才使用—例如,當玩家請求捕獲屏幕截圖時

10. 從下向上移動計算

通過沿管線向上移動計算到處理更少實例的地方,從而減少計算的總數。在管線中越早執行計算,就可以越多地減少整體操作的數量。也可以顯著減少工作量。通常在場景中,頂點數量比需要處理的片段數量要少。這意味著逐頂點處理計算,相對於逐像素,可以大大減少計算量。也可以考慮將計算從圖形核心移除。雖然圖形核心執行(計算)操作比CPU快得多,但相對於圖形核心對很多頂點執行操作,CPU只執行一次操作就會更快。爲了進一步理解這個概念,可以考慮通過烘培場景來執行離線計算,從而通過簡單的查找替換昂貴的實時計算。例如,對場景中靜態物體(如地形,建築和樹等)使用光照貼圖代替實時光照。這大大提升了性能,並且在許多情況下,比運行時計算提供了更高的光照質量。以unity舉例,如果一個模型做uv動畫,uv移動計算在CPU端要好於在頂點shader中計算,更好於在片段shader中計算。注意在CPU端是通過修改材質uv參數來做uv動畫,而不是修改模型全部頂點數據的uv值。同樣在後處理中在頂點計算一個值要比全屏像素中省的多注意不是所有操作都能從片段著色移到頂點著色中,光柵化對頂點數據進行透視校正插值,只對線性變化的屬性正確。所以在頂點中放入光照高光之類非線性計算結果是不對的。

其他因素

修改GL狀態機會導致圖形驅動的CPU開銷,因爲更改需要被解釋並轉換成可以發布到圖形核心的任務。要減少這類開銷,儘量減少API調用的數量以及應用程式端狀態修改。對於幾何體數據,儘可能多的合併網格到一個繪製調用draw call中. 示例如下:
火車上的座位網格相對彼此具有獨立的靜態位置和方向,並使用相同的渲染狀態。座位和火車可以組合成一個單一網格。繪製火車內部時,幾個繪製調用合併爲一個調用。按PowerVR硬體的隱藏面移除特性,(不透明物體)不需要按深度順序提交幾何體來減少overdraw。少了這個限制,應用程式可以專注基於渲染狀態進行繪製排序,確保最小化狀態修改。與幾何體數據類似,可以通過紋理圖集或者紋理數組將多個紋理合併到一個單一綁定對象中。然後通過適當的著色器統一變量應用紋理到每個對象上。如避免讀取/寫入正在使用的緩衝區對象中所討論的那樣,修改緩衝區數據可能導致圖形管線停滯stall或者增加圖形驅動程序分配的內存量。當合併繪製時,考慮緩衝區的更新頻率很重要。例如,將具有靜態頂點數據、空間連貫的物體合併到一個頂點緩衝區,將具有動態數據(如布料等軟體對象)合併到另外一個頂點緩衝區中。圖形驅動使用頂點緩衝區緩存頂點數據屬性,如用於將2D圖像映射到網格的紋理坐標,模型/空間位置等。對於不常更改頂點屬性的靜態對象,頂點緩衝區可以提升性能,因爲緩存了可重用於多幀渲染的數據。在上面的示例中,索引緩衝區和頂點緩衝區一起使用。索引緩衝區定義了頂點緩衝區元素訪問的順序以代表網格中的三角形。索引緩衝區可以提升性能並且縮減了複雜網格數據的存儲空間。這是因爲頂點屬性只寫入到頂點緩衝一次,然後根據需求被引用多次來表示圍繞該頂點位置的三角形。PowerVR硬體針對三角形索引列表進行了優化,對於精細的性能調整,頂點和索引緩衝區應該進行排序來提升GPU訪問數據時的緩衝效率。我們的3D場景導出和轉換工具,PVRGeoPOD, 在產生POD文件時可以自動對網格數據進行排序。現代行動裝置通常具有多個CPU核心,爲了在現代CPU架構上獲取最佳性能,應用程式儘可能使用多線程。例如,考慮在主線程上進行圖形更新,同時在單獨的工作線程上更新物理系統。通過拆分大量的工作如物理,動畫,文件I/O等到多個線程,使應用程式更高效的使用CPU。通常可以帶來更流暢的用戶體驗。如果應用程式使用Vulkan圖形API,則可以拆分繪製命令的準備(構建command buffers)到多個線程使用mediump修飾符聲明的shader變量表示16位浮點數(FP16),應用程式在適當的地方都應該用FP16, 因爲在理論上它的吞吐量是FP32(highp)的兩倍, 從而顯著提升了性能。通常使用FP32地方,需要提供足夠的精度並且最大和最小值不會溢出,以致引入視覺瑕疵細節層次是應用程式需要考慮的重要因素,這裡應該採用「足夠好」的概念。應用程式開發人員必須考慮昂貴的圖形效果和高質量資源對性能的影響。
mipmaping是一種LOD形式,在規則7已經討論過。LOD的第二種考慮因素是幾何體複雜性。應該爲每個對象或者對象一部分使用適當的幾何體複雜度級別。

以下是浪費計算和內存資源的示例:

考慮使用bump maping之類的著色器技術來減少幾何體複雜度,仍然可以保持高層次的視覺細節。對於反射pass之類的技術尤其如此,在其中大量的幾何體數據不可見在採用延遲渲染結構的圖形硬體上,如PowerVR,應用程式不需要depth pre-pass,因爲不會有性能收益。執行這個操作只會浪費時鐘周期和帶寬。因爲在片段處理開始之前,在光柵化期間硬體會自動檢測並從管線中移除被遮擋的(不透明)幾何體。對於延遲光照之類的圖形技術,通常需要附加多個顏色渲染目標到一個幀緩衝區對象,渲染所需的中間數據,然後做爲紋理採樣這些數據來實現。雖然靈活,但這種方法,即使經過優化,仍然會消耗大量的系統內存帶寬,這對行動裝置非常高昂。OpenGL ES(3.x)和Vulkan圖形API都提供了一種方法,通過片上on-chip緩衝區,實現了覆蓋相同位置像素片段著色器之間的通信,這個緩衝區只能由相同像素坐標處的著色器調用讀取和寫入。GLES擴展shader_pixel_local_storage(2)和Vulkan臨時附件使應用程式能夠將中間逐像素數據存儲在片上tile緩存中,雖然每種方法都有自己的實現細節,但它們都提供了相似的功能和相似的收益。例如,延遲光照pass的「G-Buffer」附件僅需要一次,可以存儲在tile緩存,然後再完成繪製後丟棄。上述兩種API特性對於基於tile的渲染器(如PowerVR圖形核心)非常有益,因爲它允許應用程式高效使用片上tile緩存。不需要分配中間緩衝區附件或者回寫到系統內存-它們只存在於片上tile緩存中。這對內存帶寬非常昂貴的移動和嵌入式系統非常有用。正確使用這些功能能夠顯著降低系統內存帶寬使用率。此外,對於大部分回寫中間數據到系統內存,然後在相同像素位置採樣的技術(例如延遲光照),都能使用這些API特性優化。Vulkan 是新一代圖形和計算API。它高效,精簡和現代,目標是發揮當前和未來的設備架構優勢。Vulkan適用於各種平台,如桌面PC,遊戲主機,移動和嵌入式設備。

來源:知乎,作者:topameng

原文連結:https://zhuanlan.zhihu.com/p/93998160

關於 Imagination微信號

權威發布有關Imagination公司GPU、人工智慧以及連接IP、無線IP最新資訊,提供有關物聯網、可穿戴、通信、汽車電子、醫療電子等應用信息,每日更新大量信息,讓你緊跟技術發展,歡迎關注!伸出小手按一下二維碼我們就是好朋友!