前段時間在研究SceneKit,感受到iOS 系統有不少有趣又好玩的東西,我我的是比較喜歡折騰這些技術的,在研究SceneKit 的時候,發現它有兩套渲染機制,OpenGL 和 Matal ,OpenGL 還算比較熟悉,可是Metal部分就不太清除,因而決定好好研究,一下這磨人的小妖精。編程
1.什麼是Matal?api
Metal 是一個和 OpenGL ES 相似的面向底層的圖形編程接口,經過使用相關的 api 能夠直接操做 GPU ,最先在 2014 年的 WWDC 的時候發佈,並於今年發佈了 Metal 2。 Metal框架支持GPU硬件加速、高級3D圖形渲染以及大數據並行運算。且提供了先進而精簡的API來確保框架的細粒度(fine-grain),而且在組織架構、程序處理、圖形呈現、運算指令以及指令相關數據資源的管理上都支持底層控制。其核心目的是儘量的減小CPU開銷,而將運行時產生的大部分負載交由GPU承擔安全
2.主要的技能bash
1.3D圖形渲染 2.並行運算網絡
Metal 具備特色數據結構
有步驟講解視頻以及資料.由於簡書文章沒有地方放.你們能夠加一下個人羣獲取一下。在羣裏討論一下Metal這一塊。iOS技術交流羣:923910776.多線程
使用Metal和Objective-C來建立一個有基本脈絡的應用:畫一個簡單的三角形。架構
注意:Metal應用不能跑在iOS模擬器上,它們須要一個設備,設備上裝載着蘋果A7芯片或者更新的芯片。因此須要一臺這樣的設備(iPhone 5S,iPad Air,iPad mini2)來完成代碼的測試。app
流程框架
1.配置 Device 和 Queue 2.獲取 CommandBuffer 3.配置 CommandBufferEncoder 4.配置 PipelineState 5.建立資源 6.Encoder Buffer 【若有須要的話能夠用 Threadgroups 來分組 Encoder 數據】 7.提交到 Queue 中
- 若是有技術和我討論或者想拿源碼和思惟導圖資料的, 請聯繫我時,備註一下Matal
- 加我技術交流QQ羣:923910776
初始化
新建一個普通的工程 Single View Application,在 VC 中導入 Metal Framework。
MTLDevice
都說是操做 GPU 了,固然咱們要拿到 GPU 對象,Metal 中提供了 MTLDevice 的接口,表明了 GPU。
//獲取設備
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
if (device == nil) {
NSLog(@"don't support metal !");
return;
}
複製代碼
當設備不支持 Metal 的時候會返回空。
MTLCommandQueue
有了 GPU 以後,咱們須要一個渲染隊列 MTLCommandQueue,隊列是單一隊列,確保了指令可以按順序執行,裏面的是將要渲染的指令 MTLCommandBuffer,這是個線程安全的隊列,能夠支持多個 CommandBuffer 同時編碼。 經過 MTLDevice 能夠獲取隊列
id<MTLCommandQueue> queue = self.device.newCommandQueue;
複製代碼
MTKView
要用 Metal 來直接繪製的話,須要用特殊的界面 MTKView,同時給它設置對應的 device 爲咱們上面獲取到 MTLDevice,並把它添加到當前的界面中。
_mtkView = [[MTKView alloc] initWithFrame:self.view.frame device:_device];
[self.view addSubview:_mtkView];
複製代碼
渲染
咱們配置好 MTLDevice,MTLCommandQueue 和 MTKView 以後,咱們開始準備須要渲染到界面上的內容了,就是要塞進隊列中的緩衝數據 MTLCommandBuffer 。 簡單的流程就是先構造 MTLCommandBuffer ,再配置 CommandEncoder ,包括配置資源文件,渲染管線等,再經過 CommandEncoder 進行編碼,最後才能提交到隊列中去。
MTLCommandBuffer
有了隊列以後,咱們開始構建隊列中的 MTLCommandBuffer,一開始獲取的 Buffer 是空的,要經過 MTLCommandEncoder 編碼器來 Encode ,一個 Buffer 能夠被多個 Encoder 進行編碼。
MTLCommandBuffer 是包含了多種類型的命令編碼 - 根據不一樣的 編碼器 決定 包含了哪些數據。 一般狀況下,app 的一幀就是渲染爲一個單獨的 Command Buffer。MTLCommandBuffer 是不支持重用的輕量級的對象,每次須要的時候都是獲取一個新的 Buffer。
Buffer 有方法能夠 Label ,用來增長標籤,方便調試時使用。
建立
這裏咱們經過以下方法建立
//command buffer
id<MTLCommandBuffer> commandBuffer = [_queue commandBuffer];
複製代碼
執行
監聽結果
commandBuffer.addCompletedHandler { (buffer) in
}
commandBuffer.waitUntilCompleted()
commandBuffer.addScheduledHandler { (buffer) in
}
commandBuffer.waitUntilScheduled()
複製代碼
建立 Metal 資源
接下來我須要把咱們須要繪製的內容 encode 到咱們上面生成 MTLCommandBuffer 中。我 們這裏是要畫一個三角形,因此要有三個頂點,而後須要繪製三角形的圖片。分別用 MTLBuffer 來讀入三個頂點。
在 Metal 中是歸一化的座標系,以屏幕中心爲原點(0, 0, 0),且是始終不變的。面對屏幕,你的右邊是x正軸,上面是y正軸,屏幕指向你的爲z正軸。長度單位這樣來定:窗口範圍按此單位剛好是(-1,-1)到(1,1),即屏幕左下角座標爲(-1,-1),右上角座標爲(1,1)。
因此咱們要畫在中間一個正三角形的話,三個頂點分別爲
(0.577, -0.25, 0.0, 1.0) (-0.577, -0.25, 0.0, 1.0) (0.0, 0.5, 0.0, 1.0)
Shader (着色器) 和 Pipeline (渲染管線)
能夠添加多個 Metal 文件,最後都會編譯到二進制文件default.metallib 中。 經過 Xcode 的 File - New - File 菜單,新建一個 Metal 文件。
渲染管線
着色器這邊的工做已經完成,下面咱們須要把它和咱們的 CommandBuffer 關聯起來,就須要咱們的 PipelineState 渲染管線了。
MTLCommandEncoder 編碼器
有了資源文件,渲染管線以後,咱們能夠開始作最後的步驟了,構造 MTLCommandEncoder 編碼器。 指令編碼器包括 渲染 計算 位圖複製三種編碼器。
這裏咱們是爲了渲染一個三角形,因此這裏用的是 MTLRenderCommandEncoder 。
繪製
編碼結束以後,就能夠開始準備提交到 GPU 了。 配置須要繪製的 Layer,獲取 MTKView 的 Layer 就能夠。
如今全部的工做就都完成了,運行項目就能夠看到三角形了
調試
如何進行調試和評估性能呢? 這裏 iOS 提供了兩個工具
在 WWDC 2015,蘋果發佈了 Metal Performance Shaders (MPS) 框架,iOS 9 上的一組高性能的圖像濾鏡,其實就是邊寫好的 Shaders,提供了優秀的圖像處理能力。同時還提供了高性能的矩陣運算的 Shaders ,能用來作機器學習的運算,在 GPU 上運行卷積神經網絡。
提醒廣大網友
Metal 是一門特別深的技術,可能須要你花費你半年左右的時間去學習它,但願有鍥而不捨的情深。