本系列文章是對 metalkit.org 上面MetalKit內容的全面翻譯和學習.
幾周前,在WWDC2016
,Apple
工程師釋出了一份新的文件,Metal Best Practices Guide Metal最佳實踐指南,它包含了非常有用的資訊,關於如何在你的Metal
應用中組織程式碼來獲得更好的效能.因為文件是非常全面廣泛的,我們在本文中將只列出主要的概念.一個高效的Metal
應用需要:
- 低
CPU
佔用. - 最佳的
GPU
效能. - 連續的處理器平行計算.
- 高效資源管理.
1 Resource Management 資源管理
1.1 Persistent Objects持久物件
最佳實踐:儘早建立持久物件並重用它們.
Metal
框架提供了幾個協議來管理那些貫穿你的應用整個生命週期的持久物件.這些物件建立花費很大但通常初始化一次並經常重用.不要在每個渲染迴圈或計算迴圈開始時建立這些物件.
- 先初始化你的Device和Command Queue命令佇列
- 在Build Time建立時間就編譯你的函式和庫
- 建立Pipelines管線一次並重用它們
- 預告分配資源儲存空間 要了解更多資訊,查閱文件的持久物件章節Persistent Objects
1.2 Resource Options資源設定
最佳實踐:為你的資源設定合理的儲存模式和紋理使用設定.
Metal
資源必須被合理配置來充份利用調整記憶體訪問和驅動器效能優化.資源儲存模式允許你為MTLBuffer
和MTLTexture
物件自定義儲存位置和訪問許可權.紋理使用設定允許明確宣告你想要如何使用你的MTLTexture
物件.
- 熟悉裝置記憶體模式
- 選擇合理的資源儲存模式(
iOS
和tvOS
) - 選擇合理的資源儲存模式(
OS X
) - 設定合理的紋理使用標誌
要了解更多資訊,查閱文件的資源設定章節Resource Options
1.3 Triple Buffering三重緩衝器
最佳實踐:實現三重緩衝器來更新動態緩衝器資料. 動態緩衝器資料指緩衝器內儲存的經常更新的資料.強烈推薦實現一個三重緩衝器模型,來避免每幀建立新的緩衝器及最小化幀間處理器閒置時間.
- 防止訪問衝突,減少處理器閒置時間
- 減少記憶體開銷和幀延遲
- 允許命令緩衝事務時間
- 實現三重緩衝器模型
要了解更多資訊,查閱文件的三重緩衝器章節 Triple Buffering
1.4 Buffer Bindings緩衝器繫結
最佳實踐:用合理的方法來繫結你的緩衝器資料到圖形或計算函式.
Metal
提供了若干API
設定來繫結緩衝器資料到圖形或計算函式.setVertexBytes:length:atIndex: 方法是最佳選項來繫結大量小於 4KB 的動態緩衝器資料(瞬時緩衝器)到頂點函式.如果資料大於4KB,你應該一次性建立一個MTLBuffer並在需要時更新它的內容.
要了解更多資訊,查閱文件的緩衝器繫結章節 Buffer Bindings
Display Management顯示管理
2.1 Drawables可繪製物件
最佳實踐:儘可能短暫的持有可繪製物件. 命令緩衝器在自己被排程執行之前,可以通過presentDrawable方法來排程drawable的顯示,但是,實際上drawable自己是在命令緩衝器被執行完才顯示的.
- 用MetalKit View來獲取Drawable
要了解更多資訊,查閱文件的可繪製物件章節Drawables section of the documentation.
2.2 Native Screen Scale (iOS and tvOS)原生螢幕比例
最佳實踐:以目標螢幕的精確畫素尺寸來渲染. 你的drawable的畫素尺寸應該總是匹配目標螢幕的精確畫素尺寸.這樣可以避免離屏畫素渲染,或引發額外的取樣處理.
- 用MetalKit View來支援原生螢幕比例
要了解更多資訊,查閱文件的原生螢幕比例章節 Native Screen Scal
2.3 Frame Rate (iOS and tvOS)幀率
最佳實踐:對於那些不能維持60 FPS幀率的應用,以一個穩定的幀率顯示你的drawable.
iOS
設務的螢幕重新整理率是60 Hz
.不能穩定在這段時間內完成幀渲染的應用,應該設定更低的幀率來避免卡頓.tvOS
的螢幕重新整理率一般是60 Hz
,但並不固定.
- 用MetalKit View來支援原生螢幕比例
要了解更多資訊,查閱文件的幀率章節Frame Rate
3 Command Generation命令生成
3.1 Load and Store Actions載入與儲存動作
最佳實踐:為你的渲染目標設定合理的載入與儲存動作.
在你的Metal
渲染物件上執行的動作必須被合理配置,來避免在渲染過程的開始()或xf昂貴或不必要的渲染工作.
- 選擇合理的載入動作
- 選擇合理的儲存動作
- 在渲染過程中評估動作
要了解更多資訊,查閱文件的載入與儲存動作章節Load and Store Actions
3.2 Render Command Encoders (iOS and tvOS)渲染命令編碼器
最佳實踐:儘可能的合併渲染命令編碼器. 消除不必要的渲染命令編碼器,減少記憶體頻寬佔用並提高效能.
- 評估渲染傳遞順序
- 評估取樣依賴
- 評估渲染過程中的動作
要了解更多資訊,查閱文件的渲染命令編碼器章節Render Command Encoders
3.3 Command Buffers命令緩衝器
最佳實踐:每幀提交儘可能少的命令緩衝器,充份利用GPU
.
命令緩衝器在Metal
中是提交工作的基本單位;它們由CPU
建立並被GPU
執行.這種關係允許你通過調整每幀提交的命令緩衝器數量來平衡CPU
和GPU
的工作.
要了解更多資訊,查閱文件的命令緩衝器章節Command Buffers
3.4 Indirect Buffers間接緩衝器
最佳實踐:如果你的繪製或排程呼叫引數是由GPU
動態生成的,應使用間接緩衝器.
間接緩衝器是MTLBuffer
物件,它帶有一個特殊的資料佈局來代表繪製或排程命令引數.
- 消除不必要的資料傳輸並減少處理器閒置時間
要了解更多資訊,查閱文件的命令緩衝器章節Indirect Buffers
4 Compilation
4.1 Functions and Libraries函式和庫
最佳實踐:在build生成時編譯你的函式,並生成你的庫.
編譯Metal Shading Language
原始碼是Metal
應用中耗時的階段之一.Metal
通過允許你在build時編譯圖形和計算函式並在執行時作為庫載入它們,來縮短時間花費.
- 在build時生成你的庫
- 將函式放在一個單一的庫裡面
要了解更多資訊,查閱文件的函式和庫章節 Functions and Libraries
4.2 Pipelines管線
最佳實踐:非同步build生成你的渲染和計算管線. 擁有多個渲染或計算管線允許你為特定任務使用不同的狀態配置.非同步生成這些管線可以提高效能和併發數.推薦你提前生成所有已知的管線,避免懶載入.
要了解更多資訊,查閱文件的管線章節Pipelines
這份指南,還有Metal程式設計指南 Metal Programming Guide及Metal著色語言指南Metal Shading Language Guide都已經更新到iOS 10
, tvOS 10
和OS X 10.12
,它們三部文件包含了建立高效能Metal
應用所需的一切.