---
# System prepended metadata

title: Metal Flow

---

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)

