ios - Swift Metal Shader 命令缓冲区的执行由于在执行期间将数字添加到数组值时出错而中止

标签 ios swift shader metal

我正在尝试一些非常简单的算法,使用 Metal GPU 加速来计算数组中的某些值。着色器在某些情况下会抛出错误,我将对此进行解释。 错误:由于执行期间发生错误,命令缓冲区的执行被中止。已忽略(导致先前/过多的 GPU 错误)(IOAF 代码 4)

着色器仅在将值添加到数组索引处的现有值时抛出此错误。示例:

这不会导致错误:

    kernel void shader (device int *wPointsIntensity [[buffer(0)]],
                const device uint *wPointsXCoord [[buffer(1)]],
                const device uint *wPointsYCoord [[buffer(2)]],
                device float *pixelSignalIntensity [[buffer(3)]],
                device float *pixelDistance [[buffer(4)]],
                const device uint& noOfPoints [[ buffer(5) ]],
                const device uint& width [[ buffer(6) ]],
                const device uint& height [[ buffer(7) ]],
                uint id [[ thread_position_in_grid ]]) {

//this does not throw error
for (uint wpIndex = 0; wpIndex < noOfPoints; wpIndex++) {
    for (uint heightIndex = 0; heightIndex < height; heightIndex++) {
        for (uint widthIndex = 0; widthIndex < width; widthIndex++) {

            uint pixelIndex = heightIndex * width + widthIndex;
            pixelDistance[pixelIndex] = float(pixelIndex);
            pixelSignalIntensity[pixelIndex] = float(pixelIndex);
}}}}

如果你改变

像素距离[像素索引] = float(像素索引); 与

像素距离[像素索引] += float(像素索引);

它会抛出一个错误。

这是快速代码:

var wPointsValues = [Int32](repeating:0, count: wPoints.count)
var wPointsXLocations = [Int32](repeating:0, count: wPoints.count)
var wPointsYLocations = [Int32](repeating:0, count: wPoints.count)
        for i in 0..<wPoints.count {
            wPointsValues[i] = Int32(wPoints[i].signalIntensity)
            wPointsXLocations[i] = Int32(wPoints[i].location.x)
            wPointsYLocations[i] = Int32(wPoints[i].location.y)
        }

        var numberOfWPoints:Int32 = Int32(wPoints.count)
        var int32Width = Int32(width)
        var int32Height = Int32(height)

        //output arrays

        let numberOfResults = wPoints.count * Int(width) * Int(height)
        var wPointsSignalIntensity = [Float32](repeating:0.0, count: numberOfResults)
        var wPointsDistance = [Float32](repeating:0.0, count: numberOfResults)


        //local variables
        var signalDensity:[Float32] = [Float32](repeating:0.0, count: numberOfResults)
        var signalDistance:[Float32] = [Float32](repeating:0.0, count: numberOfResults)

            //create input buffers
            let inWPointSignalValues = device.makeBuffer(bytes: wPointsValues, length: (MemoryLayout<Int32>.stride * wPoints.count), options: [])
            let inWPointXCoordBuffer = device.makeBuffer(bytes: wPointsXLocations, length: (MemoryLayout<Int32>.stride * wPoints.count), options: [])
            let inWPointYCoordBuffer = device.makeBuffer(bytes: wPointsYLocations, length: (MemoryLayout<Int32>.stride * wPoints.count), options: [])

            //create putput buffers
            let outPixelSignalIntensityBuffer = device.makeBuffer(bytes: wPointsSignalIntensity, length: (MemoryLayout<Float32>.stride * numberOfResults), options: [])
            let outPixelDistanceBuffer = device.makeBuffer(bytes: wPointsDistance, length: (MemoryLayout<Float32>.stride * numberOfResults), options: [])

            let commandBuffer = (mtlCommmandQueue?.makeCommandBuffer())!
            let computeCommandEncoder = (commandBuffer.makeComputeCommandEncoder())!
            computeCommandEncoder.setComputePipelineState(mtlComputePipelineFilter!)
            //set input buffers
            computeCommandEncoder.setBuffer(inWPointSignalValues, offset: 0, index: 0)
            computeCommandEncoder.setBuffer(inWPointXCoordBuffer, offset: 0, index: 1)
            computeCommandEncoder.setBuffer(inWPointYCoordBuffer, offset: 0, index: 2)

            //set output buffers
            computeCommandEncoder.setBuffer(outPixelSignalIntensityBuffer, offset: 0, index: 3)
            computeCommandEncoder.setBuffer(outPixelDistanceBuffer, offset: 0, index: 4)

            //set constants
            computeCommandEncoder.setBytes(&numberOfWPoints, length: MemoryLayout<Int32>.stride, index: 5)
            computeCommandEncoder.setBytes(&int32Width, length: MemoryLayout<Int32>.stride, index: 6)
            computeCommandEncoder.setBytes(&int32Height, length: MemoryLayout<Int32>.stride, index: 7)


            let threadsPerGroup = MTLSize(width:2,height:2,depth:2)
            let numThreadgroups = MTLSize(width:2, height:2, depth:2)
            computeCommandEncoder.dispatchThreadgroups(numThreadgroups, threadsPerThreadgroup: threadsPerGroup)

            let endBufferAllocation = mach_absolute_time()

            print("time for creating and setting buffert: time: \(Double(endBufferAllocation - start) / Double(NSEC_PER_SEC))")
            computeCommandEncoder.endEncoding()

            commandBuffer.commit()
            commandBuffer.waitUntilCompleted()
            let allComplete = mach_absolute_time()
        self.signalDistance = (outPixelDistanceBuffer?.contents())!
        self.signalDensity = (outPixelSignalIntensityBuffer?.contents())!

最佳答案

我有这个问题很久了,程序间歇性地崩溃了。原来我访问的是内核中还没有被缓冲区分配的内存。在内核中,我正在执行一个 for 循环 0..<5(即为每个线程输出 5 个值)但没有将 num_threads 除以 5。

当它没有崩溃时,它给出了正确的答案并且没有错误,除了“命令缓冲区的执行由于执行期间的错误而中止。导致 GPU 挂起错误(IOAF 代码 3)”被抛出。

关于ios - Swift Metal Shader 命令缓冲区的执行由于在执行期间将数字添加到数组值时出错而中止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51687616/

相关文章:

python - 使用 GLSL 的 OpenGL 阴影贴图

opengl-es - 如何在OpenGL ES2.0着色器中使用UBO

HTML <video> 占位符在 ipad 上是黑色的。我们可以改变它吗?

ios - Swift 3 : Segmented Control into TableView. 重新加载表时所选索引丢失

ios - 如何停止具有相同主次的 iBeacon 检测?

swift - 泛型、关联类型和 equatable 的问题

ios - 是否有一种方法比 NSKeyedArchiver 使用更少的内存来归档对象?

ios - 固定顶部菜单栏

ios - iOS 键盘的最大高度是多少?

javascript - Threejs 自定义着色器 - 屏幕撕裂