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)