MPSImageHistogramEqualization 抛出偏移量必须小于 [缓冲区长度] 的断言

MPSImageHistogramEqualization throws assertion that offset must be < [buffer length]

我正在尝试在 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).'

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

这似乎是 MPSImageHistogramEqualization 中专门路径中的错误,我鼓励您 file feedback 解决它。

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

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

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

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