(Console) Output?

Can I debug my metal-shading-language code using console output (like print in Swift)?

If yes, how?

If no, are there any other ways to output variables from my .metal file? (Maybe by passing data from the .metal file to my .swift file using the commandEncoder-buffer?)

I have unsuccessfully tried to pass a reference to an Int variable (which is in my .swift file) via the commandEncoder to my .metal file. In the .metal file, I assign a value to the int variable, but if I print the Int in my swift file, the assigned value is not there.

.swift file:

...
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)")
...

.metal file:

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

The console output is always myMetalOutput: 0


Here's a working solution in case somebody needs it:

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 ")
}

The shader:

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

    printBuffer = 123;

}

There are a couple of things going wrong here. First, newBufferWithBytes(_:length:) makes a copy of the data you provide, so the address that is written to is not the address of the original variable. Second, you don't seem to be waiting for the compute kernel to complete before attempting to read the result. You can either call waitUntilCompleted() on the corresponding command buffer (which blocks the current thread), or you can call addCompletedHandler() to provide a closure that will be called asynchronously when the kernel finishes running. At that point, you should be able to read back data from the buffer.

There is no facility for printing to the command line from within a Metal shader, so writing to a buffer or texture is pretty much your best option here.

链接地址: http://www.djcxy.com/p/32770.html

上一篇: 将宣传单地图合并到R中的revealjs演示文稿中

下一篇: (控制台)输出?