2016-03-14 30 views
6

我可以使用控制檯輸出(例如Swift中的print)來調試我的金屬陰影語言代碼嗎?金屬着色語言 - (控制檯)輸出?

如果是,如何?

如果否,是否有任何其他方式輸出我的.metal文件中的變量? (也許通過使用commandEncoder緩衝區將.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)") 
... 

。金屬文件:

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

控制檯輸出總是myMetalOutput: 0

回答

1

下面是萬一有人工作的解決方案需要它:

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

有一對夫婦的事情去錯在這裏。首先,newBufferWithBytes(_:length:)會提供您提供的數據的副本,因此寫入的地址不是原始變量的地址。其次,在嘗試讀取結果之前,您似乎並未等待計算內核完成。你可以在相應的命令緩衝區(阻塞當前線程)上調用waitUntilCompleted(),或者你可以調用addCompletedHandler()來提供一個閉包,當內核結束運行時這個閉包將被異步調用。此時,您應該能夠從緩衝區讀回數據。

沒有設備從金屬着色器內部打印到命令行,所以寫入緩衝區或紋理幾乎是您最好的選擇。

+1

這個答案是不完整的。你只說使用'newBufferWithBytes'是錯誤的,但不要寫什麼來代替。答案可能是'newBufferWithBytesNoCopy',但這仍然不能解決問題,我試圖返回值打印使用這個和'addCompletedHandler',它仍然打印0. – Ixx

+0

看起來OP認爲這個答案完成,由於它被接受。這聽起來像你可能有一個稍微不同的用例,爲此你可能應該開一個新的問題。 – warrenm

+0

我有完全相同的用例,打開一個新問題將被標記爲重複,所以我認爲問題出在這個答案中。 – Ixx