Lenguaje de sombreado metálico – (Consola) ¿Salida?

¿Puedo depurar mi código de lenguaje de sombreado de metal usando la salida de la console (como print en Swift)?

En caso afirmativo, ¿cómo?

Si no, ¿hay otras forms de generar variables de mi file .metal? (Tal vez al pasar datos desde el file .metal a mi file .swift usando el commandEncoder-buffer?)

Intenté infructuosamente pasar una reference a una variable Int (que está en mi file .swift) a través del commandEncoder a mi file .metal. En el file .metal, asigno un valor a la variable int, pero si imprimo el Int en mi file swift, el valor asignado no está allí.

file .swift:

 ... var myMetalOutput: Int = 0 ... let printBuffer = device.newBufferWithBytes(&myMetalOutput, length: sizeof(Int), options: MTLResourceOptions.CPUCacheModeDefaultCache) commandEncoder.setBuffer(printBuffer, offset: 0, atIndex: 8) ... commandBuffer.commit() drawable.present() print("myMetalOutput: \(myMetalOutput)") ... 

.Lima metálica:

 ... kernel void shader(..., device int &printBuffer [[8]], ...) { ... printBuffer = 123; ... } 

La salida de la console siempre es myMetalOutput: 0

Aquí hay una solución funcional en caso de que alguien lo necesite:

 let device = MTLCreateSystemDefaultDevice()! let commandQueue = device.newCommandQueue() let defaultLibrary = device.newDefaultLibrary()! let commandBuffer = commandQueue.commandBuffer() let computeCommandEncoder = commandBuffer.computeCommandEncoder() let program = defaultLibrary.newFunctionWithName("shader") do { let computePipelineFilter = try device.newComputePipelineStateWithFunction(program!) computeCommandEncoder.setComputePipelineState(computePipelineFilter) var resultdata = [Int](count: 1, repeatedValue: 0) let outVectorBuffer = device.newBufferWithBytes(&resultdata, length: sizeofValue(1), options: MTLResourceOptions.CPUCacheModeDefaultCache) computeCommandEncoder.setBuffer(outVectorBuffer, offset: 0, atIndex: 0) let threadsPerGroup = MTLSize(width:1,height:1,depth:1) let numThreadgroups = MTLSize(width:1, height:1, depth:1) computeCommandEncoder.dispatchThreadgroups(numThreadgroups, threadsPerThreadgroup: threadsPerGroup) computeCommandEncoder.endEncoding() commandBuffer.addCompletedHandler {commandBuffer in let data = NSData(bytes: outVectorBuffer.contents(), length: sizeof(NSInteger)) var out: NSInteger = 0 data.getBytes(&out, length: sizeof(NSInteger)) print("data: \(out)") } commandBuffer.commit() } catch { fatalError("newComputePipelineStateWithFunction failed ") } 

El sombreador:

 kernel void shader(device int &printBuffer [[buffer(0)]], uint id [[ thread_position_in_grid ]]) { printBuffer = 123; } 

Hay un par de cosas que salen mal aquí. Primero, newBufferWithBytes(_:length:) hace una copy de los datos que proporciona, por lo que la dirección que está escrita no es la dirección de la variable original. En segundo lugar, no parece estar esperando que el kernel de cómputo se complete antes de intentar leer el resultado. Puede llamar a waitUntilCompleted() en el búfer de commands correspondiente (que bloquea el hilo actual), o puede llamar a addCompletedHandler() para proporcionar un cierre que se llamará de forma asíncrona cuando el núcleo termine de ejecutarse. En ese momento, debería poder leer los datos del búfer.

No hay ninguna posibilidad de imprimir en la command-line desde un sombreador metálico, por lo que escribir en un búfer o textura es más o less su mejor opción aquí.

Intereting Posts