Metal에는 데이터를 제공하고 도형을 그릴 수 있는 메서드나 API가 존재하지 않음
데이터 제공 및 그리기 명령의 실행은 별도의 작업이며 가장 일반적인 유형의 Metal 명령
예시: 몇 개의 점 데이터가 포함된 버퍼가 있고, 선분을 그리려고 한다고 가정
먼저, 어떤 버퍼가 선 데이터를 보유하고 있는지 Metal에 알려야 함.
그리고 나서 Metal에게 선을 그리라고 지시함.
// 의사코드
commandList.setBuffer(pointBuffer)
commandList.drawLines(1)
GPU는 CPU와는 분리된 프로세서
우리는 둘 중 한 프로세서가 실행 중일 때, 다른 프로세서가 대기하는 상태 보다는, 2가지 프로세서가 동시에 작업이 실행되도록 하는 상태를 원함
이러한 이유로 GPU는 지정한 명령은 즉시 실행되지 않음. 대신 명령은 명령 버퍼 (Command Buffer)에 수집된 다음 배치 실행 형태로 GPU에 전달됨.
Command Queue라는 객체를 사용하여 GPU에 명령을 전달
다음 코드에서 commandQueue 객체는 MTLCommandQueue 프로토콜을 준수하는 객체임.
명령 큐의 목적은 명령으로 채울 수 있는 명령 버퍼를 생성하고, 실행할 준비가 되었을 때 명령을 GPU로 전달하는 것
device에서 명령 대기열을 만들 수 있다.
let commandQueue = device.makeCommandQueue()!
let commandBuffer = commandQueue.makeCommandBuffer()!
commandBuffer.addCompletedHandler { completeCommandBuffer in
print("Command Buffer completed")
}
commandBuffer.commit()
let sourceBuffer = device.makeBuffer(length: 16, options: [])!
let destBuffer = device.makeBuffer(length: 16, options: [])!
SIMD2<Float>타입을 binding하고 해당 요소를 설정하여 source buffer에 점 데이터를 넣기let points = sourceBuffer.contents().bindMemory(to: SIMD2<Float>.self,
capacity: 2)
points[0] = SIMD2<Float>(10, 10)
points[1] = SIMD2<Float>(100, 100)
let blitCommandEncoder = commandBuffer.makeBlitCommandEncoder()!blitCommandEncoder.copy(from: sourceBuffer,
sourceOffset: 0,
to: destBuffer,
destinationOffset: 0,
size: MemoryLayout<SIMD2<Float>>.stride * 2)blitCommandEncoder.endEncoding()
commandBuffer.addCompletedHandler { completeCommandBuffer in
let outPoints = destBuffer.contents().bindMemory(to: SIMD2<Float>.self, capacity: 2)
let p1 = outPoints[1]
print("destBuffer's p1 is \(p1)")
}
// destBuffer's p1 is SIMD2<Float>(100.0, 100.0)
출처: https://medium.com/@warrenm/thirty-days-of-metal-day-3-commands-775e5bd01438