金属着色语言 - (控制台)输出?

时间:2016-03-14 10:43:13

标签: ios metal console-output

我可以使用控制台输出调试我的金属着色语言代码(如Swift中的print)吗?

如果是,怎么样?

如果不是,还有其他方法可以从我的.metal文件中输出变量吗? (也许通过使用commandEncoder-buffer将数据从.metal文件传递到我的.swift文件?)

我尝试通过commandEncoder将对Int变量(在我的.swift文件中)的引用传递给我的.metal文件,但未成功。在.metal文件中,我为int变量赋值,但是如果我在swift文件中打印Int,则指定的值不存在。

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

.metal文件:

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

控制台输出始终为myMetalOutput: 0

2 个答案:

答案 0 :(得分:5)

如果有人需要,这是一个有效的解决方案:

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

着色器:

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

    printBuffer = 123;

}

答案 1 :(得分:4)

这里有一些问题。首先,newBufferWithBytes(_:length:)对您提供的数据进行复制,因此写入的地址不是原始变量的地址。其次,在尝试读取结果之前,您似乎没有等待计算内核完成。您可以在相应的命令缓冲区(阻塞当前线程)上调用waitUntilCompleted(),也可以调用addCompletedHandler()以提供在内核完成运行时异步调用的闭包。此时,您应该能够从缓冲区读回数据。

在Metal Shader中没有可以从命令行打印的功能,因此写入缓冲区或纹理几乎是您最好的选择。