Unity-可編程渲染管線 SRP Batcher
SRP Batcher 是一個渲染循環(huán),可通過許多使用同一著色器變體的材質(zhì)來加快場景中的 CPU 渲染速度。

啟用 SRP Batcher
要使用 SRP Batcher,項目必須使用可編程渲染管線??删幊啼秩竟芫€可以是:
通用渲染管線 (URP)。
高清渲染管線 (HDRP)。
自定義 SRP。
要在 URP 或 HDRP 中激活 SRP Batcher,請執(zhí)行以下操作:
1.在 Hierarchy 窗口中,選擇?URP 資源或?HDRP 資源。 2.在該資源的 Inspector 中,找到?Advanced?部分,然后選中?SRP Batcher?復(fù)選框。

要在運行時啟用或禁用 SRP Batcher,請在 C# 代碼中切換以下全局變量:
GraphicsSettings.useScriptableRenderPipelineBatching = true;`
支持的平臺
SRP Batcher 適用于幾乎所有平臺。下表顯示了支持的平臺以及所需的最低 Unity 版本。
Platform????????????????????????????????????????????????????Minimum Unity version required
Windows DirectX 11???????????????????????????????????????????????????2018.2
PlayStation 4??????????????????????????????????????????????????????????????2018.2
Vulkan????????????????????????????????????????????????????????????????????????2018.3
OSX Metal??????????????????????????????????????????????????????????????????2018.3
iOS Metal???????????????????????????????????????????????????????????????????2018.3
Nintendo Switch?????????????????????????????????????????????????????????2018.3
Xbox One DirectX 11?????????????????????????????????????????????????2019.2
OpenGL 4.2 and higher???????????????????????????????????????????? 2019.1
OpenGL ES 3.1 and higher???????????????????????????????????????2019.1
Xbox One DirectX 12????????????????????????????????????????????????2019.1
Windows DirectX 12???????????????????????????????????????????????? 2019.1
注意:對于 XR,只能以?SinglePassInstanced
?模式來使用 SRP Batcher。
SRP Batcher 的工作原理
Unity 中,可以在一幀內(nèi)的任何時間修改任何材質(zhì)的屬性。但是,這種做法有一些缺點。例如,DrawCall 使用新材質(zhì)時,要執(zhí)行許多作業(yè)。因此,場景中的材質(zhì)越多,Unity 必須用于設(shè)置 GPU 數(shù)據(jù)的 CPU 也越多。解決此問題的傳統(tǒng)方法是減少 DrawCall 的數(shù)量以優(yōu)化 CPU 渲染成本,因為 Unity 在發(fā)出 DrawCall 之前必須進行很多設(shè)置。實際的 CPU 成本便來自該設(shè)置,而不是來自 GPU DrawCall 本身(DrawCall 只是 Unity 需要推送到 GPU 命令緩沖區(qū)的少量字節(jié))。
SRP Batcher 通過批處理一系列?Bind
?和?Draw
?GPU 命令來減少 DrawCall 之間的 GPU 設(shè)置。

為了獲得最大渲染性能,這些批次必須盡可能大。為了實現(xiàn)這一點,可以使用盡可能多具有相同著色器的不同材質(zhì),但是必須使用盡可能少的著色器變體。
在內(nèi)渲染循環(huán)中,當 Unity 檢測到新材質(zhì)時,CPU 會收集所有屬性并在 GPU 內(nèi)存中設(shè)置不同的常量緩沖區(qū)。GPU 緩沖區(qū)的數(shù)量取決于著色器如何聲明其 CBUFFER。
為了在場景使用很多不同材質(zhì)但很少使用著色器變體的一般情況下加快速度,SRP 在原生集成了范例(例如 GPU 數(shù)據(jù)持久性)。
SRP Batcher 是一個低級渲染循環(huán),使材質(zhì)數(shù)據(jù)持久保留在 GPU 內(nèi)存中。如果材質(zhì)內(nèi)容不變,SRP Batcher 不需要設(shè)置緩沖區(qū)并將緩沖區(qū)上傳到 GPU。實際上,SRP Batcher 會使用專用的代碼路徑來快速更新大型 GPU 緩沖區(qū)中的 Unity 引擎屬性,如下所示:

在此處,CPU 僅處理上圖中標記為?Per Object large buffer?的 Unity 引擎屬性。所有材質(zhì)在 GPU 內(nèi)存中都有持久的 CBUFFER,可供隨時使用。這樣會加快渲染速度,原因是: 現(xiàn)在,所有材質(zhì)內(nèi)容都持久保留在 GPU 內(nèi)存中。 專用代碼針對所有每對象屬性,管理著一個大型的每對象 GPU CBUFFER。
SRP Batcher 兼容性
為了使 SRP Batcher 代碼路徑能夠渲染對象:
渲染的對象必須是網(wǎng)格或蒙皮網(wǎng)格。該對象不能是粒子。
著色器必須與 SRP Batcher 兼容。HDRP 和 URP 中的所有光照和無光照著色器均符合此要求(這些著色器的“粒子”版本除外)。
為了使著色器與 SRP Batcher 兼容:
必須在一個名為“UnityPerDraw”的 CBUFFER 中聲明所有內(nèi)置引擎屬性。例如:
unity_ObjectToWorld
?或?unity_SHAr
。必須在一個名為?
UnityPerMaterial
?的 CBUFFER 中聲明所有材質(zhì)屬性。
可以在 Inspector 面板中查看著色器的兼容性狀態(tài)。

在任何給定場景中,有些對象與 SRP Batcher 兼容,而有些對象則不兼容。即使在使用不兼容的對象時,Unity 也會正確渲染場景。這是因為兼容對象使用 SRP Batcher 代碼路徑,而其他對象則使用標準 SRP 代碼路徑。
使用 SRP Batcher 代碼路徑????????????????????????????????
????* 使用與 SRP Batcher 兼容的著色器的網(wǎng)格* 任何非網(wǎng)格對象(包括蒙皮網(wǎng)格)
不使用 SRP Batcher 代碼路徑
????* 任何使用非兼容著色器的網(wǎng)格
????* 使用材質(zhì)屬性塊的渲染器
使用 SRP Batcher 時的性能分析
為了測量使用 SRP Batcher 時場景中的增速,請將?SRPBatcherProfiler.cs
?C# 腳本從 SRP Batcher 模板添加到您的場景。當此腳本正在運行時: 使用 F8 鍵來切換覆蓋顯示。 也可以在運行過程中使用 F9 鍵來打開和關(guān)閉 SRP Batcher。
此覆蓋如下所示:

時間測量值以毫秒 (ms) 為單位,并顯示 CPU 在 Unity SRP 渲染循環(huán)中花費的時間。
注意:此處的時間等于在一幀內(nèi)調(diào)用的所有?RenderLoop.Draw
?和?Shadows.Draw
?標記的累積時間(與線程所有者無關(guān))。例如,如果看到 1.31ms SRP Batcher 代碼路徑,表示繪制調(diào)用可能在主線程上花費了 0.31ms,并且 1ms 分散在所有圖形作業(yè)中。
覆蓋信息
下表描述了在運行模式下可見的 SRP Batcher 覆蓋中的每個設(shè)置:
覆蓋中的名稱描述(SRP batcher ON)/(SRP batcher OFF)????????????????????????指示是否已啟用當前的 SRP Batcher。要打開或關(guān)閉 SRP Batcher,請按 F9。
CPU Rendering time指示 SRP 循環(huán)在 CPU 中花費的總累積時間,無論使用的是哪種多線程模式(例如單個客戶端/工作線程或圖形作業(yè))。在這里可以最大限度看到 SRP Batcher 的效果。要查看 SRP Batcher 的優(yōu)化,請嘗試將其打開和關(guān)閉來查看 CPU 使用率的差異。在上述示例中,總時間為 2.11 毫秒。
(incl RT idle):__指示 SRP 在渲染線程中花費的空閑時間。這可能意味著應(yīng)用程序處于沒有任何圖形作業(yè)的客戶端/工作模式;在渲染線程必須等待主線程上的圖形命令時會發(fā)生此情況。在以上示例中,渲染線程空閑了 0.36 毫秒。| ||SRP Batcher code path (flushes)|指示您的游戲或應(yīng)用程序花費在 SRP Batcher 代碼路徑中的時間。此時間包括游戲渲染?All objects__(陰影通道除外)(1.18ms) 和?Shadows?(1.13ms) 這兩個方面。如果?Shadows?數(shù)量較大,請嘗試減少場景中陰影投射光源的數(shù)量,或在渲染管線資源中選擇較少數(shù)量的級聯(lián)。在以上示例中,該時間為 1.31ms。
(flush)?數(shù)字表示 Unity 由于遇到新著色器變體而刷新場景的次數(shù)(在此示例中為 89)。較少的刷新次數(shù)總是更好一些,因為這意味著幀中的著色器變體數(shù)量較少。
Standard code path (flushes)指示 Unity 在渲染與 SRP Batcher 不兼容的對象(例如蒙皮網(wǎng)格或粒子)方面花費的時間。
在以上示例中,SRP Batcher 在 0.80 毫秒內(nèi)刷新了 81 個對象:陰影通道為 0.09 毫秒,所有其他通道為 0.71 毫秒。
Global Main Loop: (FPS)指示全局主循環(huán)時間(以毫秒為單位)以及等效的每秒幀數(shù) (FPS)。注意:FPS 并非線性,因此,如果發(fā)現(xiàn) FPS 增加 20,不一定意味著已經(jīng)優(yōu)化場景。若要查看 SRP Batcher 是否優(yōu)化了場景渲染,請開啟和關(guān)閉該功能,然后比較?CPU Rendering time?下的數(shù)字。
Unity 幀調(diào)試器中的 SRP Batcher 數(shù)據(jù)
可以在?Frame Debugger?窗口中檢查 SRP Batcher“批次”的狀態(tài)。
要檢查 SRP Batcher 批次的狀態(tài),請執(zhí)行以下操作:
1.在 Editor 中,選擇?Window?>?Analysis?>?Frame Debugger?>?Render Camera?>?Render Opaques__,然后展開?RenderLoopNewBatcher.Draw__ 列表。 2.單擊要檢查的?SRP Batch。
SRP Batch?詳細信息可以顯示使用了多少個繪制調(diào)用、著色器附加了哪些關(guān)鍵字以及該特定繪制調(diào)用未與前一個調(diào)用一起接受批處理的原因。在以下示例中,所述原因是:_Node use different shader keywords_。這意味著該批次的著色器關(guān)鍵字不同于前一個批次中的關(guān)鍵字。由于 SRP Batcher 使用了另一個不同的著色器變體,因此這一批次已破壞。如果一個 SRP 批次的繪制調(diào)用數(shù)量較少,您很可能使用了太多的著色器變體。

如果您要編寫自己的 SRP 而不是使用 URP 或 HDRP,請嘗試使用最少的關(guān)鍵字來編寫通用的“超級”著色器(但可以在每個材質(zhì)中使用盡可能多的材質(zhì)參數(shù)和材質(zhì)屬性)。