0

我正在尝试在 iOS 上使用 MPSImageHistogramEqualization 进行直方图均衡化,但它最终抛出了一个我不理解的断言。这是我的代码:

    // Calculate Histogram
    var histogramInfo = MPSImageHistogramInfo(
        numberOfHistogramEntries: 256,
        histogramForAlpha: false,
        minPixelValue: vector_float4(0,0,0,0),
        maxPixelValue: vector_float4(1,1,1,1))
    let calculation = MPSImageHistogram(device: self.mtlDevice, histogramInfo: &histogramInfo)
    let bufferLength = calculation.histogramSize(forSourceFormat: sourceTexture.pixelFormat)
    let histogramInfoBuffer = self.mtlDevice.makeBuffer(length: bufferLength, options: [.storageModePrivate])!
    calculation.encode(to: commandBuffer,
                       sourceTexture: sourceTexture,
                       histogram: histogramInfoBuffer,
                       histogramOffset: 0)
    let histogramEqualization = MPSImageHistogramEqualization(device: self.mtlDevice, histogramInfo: &histogramInfo)
    histogramEqualization.encodeTransform(to: commandBuffer, sourceTexture: sourceTexture, histogram: histogramInfoBuffer, histogramOffset: 0)

这是发生在最后一行的结果断言:

-[MTLDebugComputeCommandEncoder setBuffer:offset:atIndex:]:283: failed assertion `offset(4096) must be < [buffer length](4096).'

关于这里可能发生的事情有什么建议吗?

4

1 回答 1

2

这似乎是 中的专用路径中的错误MPSImageHistogramEqualization,我鼓励您提交反馈

numberOfHistogramEntries大于 256 时,图像内核分配一个足够大的内部缓冲区来保存它需要处理的数据(对于 N=512,这是 8192 字节),加上一个额外的空间(32 字节)。当optimized256BinsUseCase设置了内部标志时,它正好分配了 4096 字节,省略了最后一位额外的存储空间。我的怀疑是后续操作依赖于在初始数据块之后有更多空间,并且无意中将缓冲区偏移量设置为超过内部缓冲区的长度。

您可以通过使用不同数量的直方图箱(例如 512)来解决此问题。这会浪费一点空间和时间,但我认为它会产生相同的结果。

或者,您可以通过禁用 Metal 验证层来避免这种崩溃,但我强烈反对这样做,因为您只会掩盖潜在的问题,直到它得到修复。

注意:我在 macOS Catalina 上对 MetalPerformanceShaders 框架进行了逆向工程。不同的平台和不同的软件版本可能有不同的代码路径。

于 2019-10-15T20:08:33.050 回答