[GDC2017]節點化:寒霜引擎可擴展的渲染管線架構

[GDC2017]節點化:寒霜引擎可擴展的渲染管線架構

來自專欄 遊戲開發套路

FrameGraph-Extensible_Rendering_Architecture_in_Frostbite

  • 改進引擎的擴展性
  • 簡化一步計算
  • ESRAM

  • DICE次時代引擎
  • EA引擎

遊戲列表

07年引擎的渲染系統

  • 對比17年的
  • 除了綠色部分,整體架構貌似差不多

  • 簡版的渲染系統
  • 前向、後向
  • 渲染上下文(RC),
  • WR:

  • 詳細解釋一下WR
  • 代碼驅動?
  • 負責分配渲染資源(RT,Buffers)

戰地4 用到渲染特性

  • WR的挑戰:
  • 資源管理
    • 各自手工管理ESRAM
    • 每個Team有各自的實現方式
  • 和渲染系統高耦合
  • 可擴展性差
  • 代碼量:4k行上漲到15K行
    • 單個函數超過2k行
    • 維護代碼合併、集成代碼代價很大

  • 將WR模塊化實現目標:
    • 抽象出整個管線的模塊
    • 改進可擴展性
      • 低耦合、組件式代碼模塊
      • 自動化資源管理
    • 可視化、可調試

  • 新架構中,添加了FrameGraph和Transient Resouces
  • FG可以抽象出渲染管線各個模塊

現在解釋一下FG

  • FG主要解決的問題
    • 能構建整個幀圖的節點
      • 簡化資源管理
      • 簡化渲染管線的配置
      • 簡化非同步計算和資源內存屏障
    • 能DIY,組裝
    • 可視化和Debug

舉一個FG的例子

  • 橙色節點是渲染操作節點,藍色節點是資源節點
  • 非循環,單向流
  • 能看到整個渲染管線流程

戰地4中的一個FrameGraph

  • 上百個Pass和Resouce節點
  • 超級大的Graph

演示內存分布

  • 脫離Immediate mode
  • 渲染的代碼抽取到passes
  • 多階段 retained mode
    • Setup
    • Compile
    • Execute
  • 這樣做就是要統一模式,固定?
  • 代碼驅動架構?

詳細介紹FG的每個階段

  • Setup -> Compile -> Execute
  • 解釋Setup階段
    • 定義了RenderPass和ComputePass
    • 定義了資源的輸入輸出
    • 代碼流程類似於ImmediateMode

  • 在RenderPass中需要控制所有可用資源
    • 可讀
    • 可寫
    • 可創建
  • 其他 常駐資源 用Import形式到FrameGraph
    • Historybuffer
    • BackBuffer
    • 全局buffer?
    • 固定

舉例說明一個Resource例子

  • 創建一個renderTarget

Setup的一個例子

高級操作

  • 高級操作
    • 延遲創建資源
    • 繼承資源參數
    • 移動子資源?

解釋MoveSubresource

  • 延遲渲染模塊到反射渲染模塊
    • move操作
  • 解釋MoveSubresource

編譯階段

  • 去除沒有引用到的資源
  • 分配具體的GPU資源

這就是culling的例子

  • 直接去掉Lighting過程
  • 插入DebugView
  • 再將結果Move到FinalTarget上

  • 執行階段:
    • 執行回調
    • ImmediateMode(立即模式)
      • 調用渲染API
      • 設置state、resource、Shader
      • Draw、Dispatch
    • 在這個階段獲取GPU的實際使用資源(GPU層)

  • 非同步計算:
    • 自動繼承過來
    • 手動控制的問題
      • 內存增長
      • 濫用影響性能

  • 主線程到非同步線程過程

  • 採用C++類形式改造的問題:
    • 破壞代碼流程
    • 需要大量引用?
    • 導出現有代碼到C++類太費力
  • 考慮使用 C++Lambdas (C++14)
    • 保存原有代碼流程
    • 在原有基礎上最小的改動
      • 在原有代碼上包裹一層Lambda
      • 添加一個ResourceUsage定義

用C++lambdas語法寫Pass 一個例子

  • &和= 重載?

  • 渲染模塊(每種Feature?)
  • 渲染模塊有兩種類型
    • 獨立無狀態函數?
      • 輸入輸出是FG的Resource
      • 可以嵌套Pass
      • 這個是最常用的類型
    • 常駐類型
      • 常駐資源相關(LUTs History buffers)
  • WR 層仍然屬於高層級的渲染層
    • 不會去分配GPU資源
    • 僅僅是控制各個渲染模塊的開關
    • 更加易於擴展
    • 代碼量從15K行減到5K行

modules之間的通信

  • 通過blackboard(黑板)通信
    • component的hash表
  • 舉例說明
    • BlurModule和TonemapModule通信
    • blackboard.get<BlurPyramidData>

臨時資源管理

臨時資源系統

  • 不同平台下的不同處理
    • XB1
    • DX12 PS4
    • DX11
  • Texture的內存池

PS4上面的Texture的例子

DX12上,分不同Heap

XB1上,LightBuffer被分開了,

  • 在不同時期分配不同地址
  • XB1上,LightBuffer被分開了,
    • 因為隨申請隨用?

【關於內存對齊的一些建議】

  • 優先考慮DiscardResource而不是Clear

對齊內存屏障(barriers)

對齊內存屏障的例子

  • CS Compute share
  • PS Pixel Share

  • 以戰地4為例
  • 147M為沒有對齊的內存
  • 不同平台的數據,對齊後的數據
    • DX12 80M
    • PS4 77M
    • XB1 76M

【總結】

  • full frame knowledge
  • Frame Graphs

【將來的工作】

他的Blog

grahamhazel.com/blog/


推薦閱讀:

TAG:架構 | 遊戲開發 | 虛幻4遊戲引擎 |