What I'm trying to do
I have an [[Int]]
in Swift and I'm trying to pass it into Metal through a buffer. Basically, I'm trying to use Metal to add two matrices multithreaded and give them back to Swift. So far, this is more difficult than expected.
The problem
Metal tells me that my graph isn't a pointer and I suspect I'm passing it into Metal wrong.
import MetalKit
let graph: [[Int]] = [
[0, 1, 2, 999, 999, 999],
[1, 0, 999, 5, 1, 999],
[2, 999, 0, 2, 3, 999],
[999, 5, 2, 0, 2, 2],
[999, 1, 3, 2, 0, 1],
[999, 999, 999, 2, 1, 0]]
func fooFunc(gra: [[Int]]) {
let count = gra.count
let device = MTLCreateSystemDefaultDevice()
let commandQueue = device?.makeCommandQueue()
let gpuFunctionLibrary = device?.makeDefaultLibrary()
let funcGPUFunction = gpuFunctionLibrary?.makeFunction(name: "MetalFunc")
var funcPipelineState: MTLComputePipelineState!
do {
funcPipelineState = try device?.makeComputePipelineState(function: funcGPUFunction!)
} catch {
print(error)
}
let graphBuff = device?.makeBuffer(bytes: gra,
length: MemoryLayout<Int>.size * count * count,
options: .storageModeShared)
let resultBuff = device?.makeBuffer(length: MemoryLayout<Int>.size * count,
options: .storageModeShared)
let commandBuffer = commandQueue?.makeCommandBuffer()
let commandEncoder = commandBuffer?.makeComputeCommandEncoder()
commandEncoder?.setComputePipelineState(additionComputePipelineState)
commandEncoder?.setBuffer(graphBuff, offset: 0, index: 0)
commandEncoder?.setBuffer(resultBuff, offset: 0, index: 1)
let threadsPerGrid = MTLSize(width: count, height: 1, depth: 1)
let maxThreadsPerThreadgroup = additionComputePipelineState.maxTotalThreadsPerThreadgroup // 1024
let threadsPerThreadgroup = MTLSize(width: maxThreadsPerThreadgroup, height: 1, depth: 1)
commandEncoder?.dispatchThreads(threadsPerGrid,
threadsPerThreadgroup: threadsPerThreadgroup)
commandEncoder?.endEncoding()
commandBuffer?.commit()
commandBuffer?.waitUntilCompleted()
let resultBufferPointer = resultBuff?.contents().bindMemory(to: Int.self,
capacity: MemoryLayout<Int>.size * count)
print("Result: \(Int(resultBufferPointer!.pointee) as Any)")
}
gpuDijkstra(gra: graph)
#include <metal_stdlib>
using namespace metal;
kernel void MetalFunc(constant int *graph [[ buffer(0) ]],
constant int *result [[ buffer(1) ]],
uint index [[ thread_position_in_grid ]]
{
const int size = sizeof(*graph);
int result[size][size];
for(int k = 0; k<size; k++){
result[index][k]=graph[index][k]+graph[index][k]; //ERROR: Subscripted value is not an array, pointer, or vector
}
}