2016-12-11 2 views
1

J'ai commencé avec Metalkit et j'ai un noyau très simple comme cas de test.Metalkit: MTLBuffer et pointeurs dans swift 3

kernel void compute(device float* outData [[ buffer(0) ]]) 
{ 
    outData[0] = 234.5; 
    outData[3] = 345.6; 
} 

Ces données "calculée" est stockée dans un MTLBuffer.

var buffer : MTLBuffer? 
... 
buffer = device.makeBuffer(length: MemoryLayout<Float>.size * 5, options: []) 
... 
commandBuffer.waitUntilCompleted() 

A ce stade, le noyau a écrit des données de test au MTLBuffer. Question est comment je devrais accéder à ces données de mon programme principal? Je reçois un unsafeMutableRawPointer de buffer.contents(). Comment obtenir un tableau rapide de valeurs que je peux utiliser partout ailleurs (affichage à l'écran, écriture dans un fichier, ...)?

Ces extraits travaillent dans cette application très simple, mais je ne sais pas si elles sont correctes:

let raw = buffer.contents() 
let b = raw.bindMemory(to: Float.self, capacity: 5) 
print(b.advanced(by: 3).pointee) 

let a = raw.assumingMemoryBound(to: Float.self) 
print(a.advanced(by: 3).pointee) 


let bufferPointer = UnsafeBufferPointer(start: b, count: 5) 
let values = Array(bufferPointer) 
print(values) 


let value = raw.load(fromByteOffset: MemoryLayout<Float>.size * 3, as: Float.self) 
print(value) 

deux travaillent bindMemory et assumingMemoryBound. Bien que assumingMemoryBound suppose que les octets sous-jacents sont déjà typés et bindMemory non. Je pense que l'un des deux devrait fonctionner, mais pas les deux. Lequel devrait-il être et pourquoi?

Répondre

0

J'utilise le code présenté ci-dessous pour charger des tableaux, mais je ne peux pas décider si le mien ou votre version est le meilleur.

let count = 16 

var array = [Float]() 
array.reserveCapacity(count) 

    for i in 0..<count { 
     array.append(buffer.contents().load(fromByteOffset: MemoryLayout<Float>.size * i, as: Float.self)) 
    } 
+0

Cela fait un moment que je l'ai regardé, donc je (toujours) ne sais pas quelle devrait être la réponse. Cela dit, votre version copie l'octet de données par octet. Copier des octets juste pour l'obtenir dans un autre conteneur est un drapeau rouge pour moi. Est-il vraiment nécessaire de faire une copie? – user965972

+1

@ user965972 Pour autant que je sache, c'est la seule façon de le faire, mais je n'ai pas regardé 'UnsafeBufferPointer'. Je ne suis ni très doué au niveau bas, mais je pensais au moins pouvoir donner une solution temporaire. Si j'ai raison, vous pouvez partager de la mémoire entre le processeur et le GPU, donc il pourrait y avoir un meilleur moyen de charger des données à partir d'un MTLBuffer. – Andreas