我正在尝试通过Metal iOS Swift示例来了解他们建议的三重缓冲实践。这显示在演示内部,用于统一动画。
据我了解,对齐内存只是以一个特定的增量开始,该增量是设备真正喜欢的某个字节数的倍数。我的困惑是这行代码
// The 256 byte aligned size of our uniform structure
let alignedUniformsSize = (MemoryLayout<Uniforms>.size & ~0xFF) + 0x100
他们用它来查找Uniforms结构的大小和字节。我很困惑为什么在这里有二进制操作我真的不确定他们做了什么。
如果有帮助,这个对齐的大小用于创建这样的缓冲区。我很确定缓冲区会自动分配字节对齐的内存,因此可以用作制服的内存存储位置。
let buffer = self.device.makeBuffer(length:alignedUniformsSize * 3, options:[MTLResourceOptions.storageModeShared])
所以基本上不是经历自己分配字节对齐内存的麻烦,而是让金属为它们做。
他们使用let allignedUniformsSize =
时使用的策略是否适用于Int
或Float
等其他类型的策略?
答案 0 :(得分:16)
让我们首先谈谈为什么你想要对齐缓冲区,然后我们可以谈谈逐位运算。
我们的目标是分配一个可以存储我们制服的三个(三重缓冲)副本的金属缓冲区(这样我们可以在GPU从另一个读取时写入缓冲区的一部分)。为了从这三个副本中读取每个副本,我们在绑定缓冲区时提供偏移量,如currentBufferIndex * uniformsSize
。某些金属设备要求这些偏移量为256的倍数,因此我们需要使用类似currentBufferIndex * alignedUniformsSize
的偏移量作为偏移量。
我们如何将整数“舍入”到256的下一个最高倍数?我们可以通过删除“未对齐”大小的最低8位来实现它,有效地向下舍入,然后添加256,这使我们成为下一个最高倍数。舍入部分通过按位AND运算得到,其1的补码(~
)为255,其中(32位)为0xFFFFFF00。仅通过添加0x100(即256)来完成舍入。
有趣的是,如果基本大小已经对齐,则该技术无论如何都会虚假地舍入(例如,从256到512)。对于整数除法的成本,您可以避免这种浪费:
let alignedUniformsSize = ((MemoryLayout<Uniforms>.size + 255) / 256) * 256