Metal Flow == `var ...` create once `let ...` create when use # Init Device :point_right: MTLDevice ``` var device: MTLDevice? = MTLCreateSystemDefaultDevice() ``` # Extract Texture From Frame :point_right: MTLTexture ``` let pixelBuffer: CVPixelBuffer = callback with frame var cache: CVMetalTextureCache? CVMetalTextureCache; CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, device, nil, &cache) let texture: MTLTexture? let width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0) let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0) CVMetalTextureCacheCreateTextureFromImage( kCFAllocatorDefault, cache, pixelBuffer, nil, MTLPixelFormat.bgra8Unorm, width, height, 0, &texture) // maintain reference until draw complete var member_pixelBuffer = pixelBuffer ``` # Create Vetex/Texture/Coord Shader :point_right: MTLBuffer x3 ``` var library: MTLLibrary? = device.makeDefaultLibrary() var vectexFunction: MTLFunction? = library.makeFunction(name: "passthroughVertexShader") var fragmentFunction: MTLFunction? = library.makeFunction(name: "textureQuadFragmentShader") let vertexArray: [Float] = [ -1.0, 1.0, 0, 1, -1.0, -1.0, 0, 1, 1.0, -1.0, 0, 1, -1.0, 1.0, 0, 1, 1.0, -1.0, 0, 1, 1.0, 1.0, 0, 1 ] let colorArray: [Float] = ... let textureCoordArray: [Float] = ... let vertexBuffer: MTLBuffer? = device.makeBuffer( bytes: vertexArray, length: vertexArray.count * MemoryLayout.size(ofValue: vertexArray) options: .storageModeShared) let colorBuffer: MTLBuffer? = device.makeBuffer(...) let textureCoordBuffer: MTLBuffer? = device.makeBuffer(...) ``` # Config Render Pipeline :point_right: MTLRenderPipelineState ``` let renderPassthroughDescriptor: MTLRenderPassDescriptor = MTLRenderPassDescriptor() renderPassDescriptor.colorAttachments[0].texture = texture renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 1.0) renderPassDescriptor.colorAttachments[0].loadAction = .clear renderPassDescriptor.colorAttachments[0].storeAction = .store let renderDescriptor: MTLRenderPassDescriptor = MTLRenderPassDescriptor() pipelineDescriptor.label = "Render Pipeline" pipelineDescriptor.vertexFunction = vertexFunction pipelineDescriptor.fragmentFunction = fragmentFunction pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat.bgra8Unorm pipelineDescriptor.colorAttachments[0].isBlendingEnabled = false let renderState: MTLRenderPipelineState = device.makeRenderPipelineState(descriptor: renderDescriptor) ``` # Draw :point_right: drawPrimitives(...) ``` var commandQueue: MTLCommandQueue? = device.makeCommandQueue() let commandBuffer: MTLCommandBuffer? = commandQueue.makeCommandBuffer() commandBuffer.label = "MyCommand" let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) encoder.label = "MyEncoder" encoder.setRenderPipelineState(renderState) encoder.setVertexBuffer(vertexBuffer, offset:0, at:0) encoder.setVertexBuffer(colorBuffer, offset:0, at:1) encoder.setVertexBuffer(textureCoordBuffer, offset: 0, at: 2) encoder.setFragmentTexture(texture, at:0) encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6, instanceCount: 1) encoder.endEncoding() commandBuffer.addCompletedHandler({ _ in self.member_pixelBuffer = nil // Release the reference to the pixel buffers. }) commandBuffer.commit() ``` # Reference - [developer.apple.com AVCustomEdit-Swift/APLDiagonalWipeRenderer.swift](https://developer.apple.com/library/archive/samplecode/AVCustomEdit/Listings/AVCustomEdit_Swift_APLDiagonalWipeRenderer_swift.html#//apple_ref/doc/uid/DTS40013411-AVCustomEdit_Swift_APLDiagonalWipeRenderer_swift-DontLinkElementID_24) - [developer.apple.com AVCustomEdit-Swift/APLMetalRenderer.swift](https://developer.apple.com/library/archive/samplecode/AVCustomEdit/Listings/AVCustomEdit_Swift_APLMetalRenderer_swift.html#//apple_ref/doc/uid/DTS40013411-AVCustomEdit_Swift_APLMetalRenderer_swift-DontLinkElementID_26)