基于Metal Camera開(kāi)發(fā)2:手勢(shì)劃動(dòng)切換濾鏡傳遞多個(gè)紋理到Compute Shader的實(shí)現(xiàn)思路,本文檔描述Metal Compute Shader實(shí)現(xiàn)GPUImage多級(jí)濾鏡疊加效果(多通濾波)的基本編程步驟滞伟。
文檔結(jié)構(gòu):
- Metal Compute Shader多級(jí)濾鏡疊加效果(多通濾波)的基本編程步驟介紹
- 創(chuàng)建中間紋理
- 討論:Xcode調(diào)試Metal的缺點(diǎn)
1. Metal Compute Shader多級(jí)濾鏡疊加效果(多通濾波)的基本編程步驟介紹
根據(jù)自己的實(shí)踐腺阳,簡(jiǎn)要總結(jié)Metal Compute Shader多級(jí)濾鏡疊加效果(多通濾波)的基本編程步驟如下:
- 創(chuàng)建存儲(chǔ)濾鏡處理中間結(jié)果的紋理
- 一次濾鏡(濾波)對(duì)應(yīng)一個(gè)管線狀態(tài)(ComputePipelineState)、緩沖區(qū)(CommandBuffer)與編碼器(ComputeCommandEncoder)于置。
- 前一級(jí)濾鏡的輸出 = 后一級(jí)濾鏡的輸入茧吊,最后輸出到屏幕或編碼寫到MP4等文件
參考代碼:
guard let commandBuffer_gamma = commandQueue?.makeCommandBuffer() else {
return
}
commandBuffer_gamma.label = "gamma correction"
let encoder_gamma = commandBuffer_gamma.makeComputeCommandEncoder()
encoder_gamma.label = "gamma correction"
encoder_gamma.setComputePipelineState(gammaFilter!)
encoder_gamma.setTexture(outputTexture, at: 0)
encoder_gamma.setTexture(outputTexture2, at: 1)
encoder_gamma.dispatchThreadgroups(threadgroups, threadsPerThreadgroup: threads)
encoder_gamma.endEncoding()
commandBuffer_gamma.commit()
commandBuffer_gamma.waitUntilCompleted()
guard let commandBuffer_passThrough = commandQueue?.makeCommandBuffer() else {
return
}
commandBuffer_passThrough.label = "pass through"
let encoder_passThrough = commandBuffer_passThrough.makeComputeCommandEncoder()
encoder_passThrough.label = "pass through"
encoder_passThrough.setComputePipelineState(passThroughFilter!)
encoder_passThrough.setTexture(outputTexture2, at: 0)
encoder_passThrough.setTexture(drawable.texture, at: 1)
encoder_passThrough.dispatchThreadgroups(threadgroups, threadsPerThreadgroup: threads)
encoder_passThrough.endEncoding()
commandBuffer_passThrough.present(drawable)
commandBuffer_passThrough.commit()
commandBuffer_passThrough.waitUntilCompleted()
處理1080p圖像的消耗如下圖所示贞岭。
上述為基本實(shí)現(xiàn)。由于創(chuàng)建CommandBuffer也會(huì)消耗較多CPU時(shí)間搓侄,為了提高性能瞄桨,可以創(chuàng)建一個(gè)CommandBuffer、多個(gè)CommandEncoder讶踪,即每次濾波對(duì)應(yīng)一個(gè)CommandEncoder及其ComputePipelineState芯侥。
單CommandBuffer多CommendEncoder的GPU執(zhí)行棧也非常直觀。
2. 創(chuàng)建中間紋理
MTLTextureDescriptor類描述了創(chuàng)建紋理的相關(guān)信息乳讥,設(shè)置紋理顏色格式柱查、寬度等信息后,調(diào)用MTLDevice. makeTexture即可創(chuàng)建一個(gè)空白內(nèi)容的紋理云石。參考代碼如下唉工。
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: self.colorPixelFormat, width: 1080, height: 1920, mipmapped: false)
outputTexture = device?.makeTexture(descriptor: textureDescriptor)
3. 討論:Xcode 8.3.2調(diào)試Metal的缺點(diǎn)
在調(diào)試Compute Shader及Vertex與Fragment Shader配合使用的兩種場(chǎng)景,我發(fā)現(xiàn)攝像頭上傳的BGRA紋理始終無(wú)法預(yù)覽汹忠,而Xcode調(diào)試OpenGL ES卻是可以正沉芟酰看到攝像頭上傳的紋理數(shù)據(jù),相比之下宽菜,不得不說(shuō)這是個(gè)缺點(diǎn)谣膳。不設(shè)置CommandBuffer和CommandEncoder的label時(shí),Metal的命令隊(duì)列閱讀略為困難铅乡,如圖1所示参歹。
設(shè)置CommandBuffer和CommandEncoder的label后,比OpenGL ES的命令隊(duì)列更清晰隆判,如圖2所示犬庇。
同時(shí),CommandBuffer和CommandEncoder的label也反應(yīng)在Metal System Trace侨嘀,非常方便定位性能瓶頸臭挽,如圖3所示。
默認(rèn)情況下咬腕,沒(méi)label時(shí)Metal System Trace也難以閱讀欢峰,如圖4所示。