ios – 将未对齐的缓冲区提供给MTLBuffer是否安全?

当尝试使用Metal从内存中快速将像素缓冲区绘制到屏幕时,我们使用MTLDevice.makeBuffer(bytesNoCopy:..)创建MTLBuffer对象,以允许GPU直接从内存中读取像素而无需复制它.共享内存实际上是实现良好像素传输性能的必备条件.

问题是makeBuffer需要页面对齐的内存地址和页面对齐的长度.这些要求不仅在文档中 – 它们也是使用运行时断言强制执行的.

我写的代码必须处理各种传入的分辨率和像素格式,偶尔我会得到未对齐的缓冲区或未对齐的长度.在研究了这个之后,我发现了一个允许我为这些实例使用共享内存的hack.

基本上我所做的是将未对齐的缓冲区地址向下舍入到最近的页面边界,并使用makeTexture中的offset参数来确保GPU从正确的位置开始读取.然后我将长度向上舍入到最接近的页面大小.显然内存将是有效的(因为分配只能在页面边界上发生),我认为可以安全地假设GPU没有写入或破坏该内存.

这是我用来从未对齐的缓冲区分配共享缓冲区的代码:

extension MTLDevice {
    func makeTextureFromUnalignedBuffer(textureDescriptor : MTLTextureDescriptor,bufferPtr : UnsafeMutableRawPointer,bufferLength : UInt,bytesPerRow : Int) -> MTLTexture? {

        var calculatedBufferLength = bufferLength
        let pageSize = UInt(getpagesize())
        let pageSizeBitmask = UInt(getpagesize()) - 1

        let alignedBufferAddr = UnsafeMutableRawPointer(bitPattern: UInt(bitPattern: bufferPtr) & ~pageSizeBitmask)
        let offset = UInt(bitPattern: bufferPtr) & pageSizeBitmask

        assert(bytesPerRow % 64 == 0 && offset % 64 == 0,"Supplied bufferPtr and bytesPerRow must be aligned on a 64-byte boundary!")

        calculatedBufferLength += offset

        if (calculatedBufferLength & pageSizeBitmask) != 0 {
            calculatedBufferLength &= ~(pageSize - 1)
            calculatedBufferLength += pageSize
        }

        let buffer = self.makeBuffer(bytesNoCopy: alignedBufferAddr!,length: Int(calculatedBufferLength),options: .storageModeShared,deallocator: nil)
        return buffer.makeTexture(descriptor: textureDescriptor,offset: Int(offset),bytesPerRow: bytesPerRow)
    }
}

我已经在许多不同的缓冲区上测试了它,它似乎工作得很好(仅在iOS上测试,而不是在macOS上测试).我的问题是:这种方法安全吗?任何明显的原因,为什么这不起作用?

再说一次,如果它是安全的,为什么首先强加要求?为什么API不是这样做的呢?

解决方法

我已就此问题提交了Apple TSI(技术支持事件),答案基本上是肯定的,这是安全的.以下是有兴趣的人的确切回复:

After discussing your approach with engineering we concluded that it
was valid and safe. Some noteworthy quotes:

“The framework shouldn’t care about the fact that the user doesn’t own
the entire page,because it shouldn’t ever read before the offset
where the valid data begins.”

“It really shouldn’t [care],but in general if the developer can use
page-allocators rather than malloc for their incoming images,that
would be nice.”

As to why the alignment constraints/assertions are in place:

“Typically mapping memory you don’t own into another address space is a bit icky,even if it works in practice. This is one reason why we required mapping to be page aligned,because the hardware really is mapping (and gaining write access) to the entire page.”

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...