这段代码如何在swift中找到struct的内存对齐大小?为什么需要二元操作?

问题描述:

我正在通过Metal iOS Swift示例尝试理解他们所建议的三重缓冲实践。这显示在统一动画的演示中。这段代码如何在swift中找到struct的内存对齐大小?为什么需要二元操作?

据我所知,它对齐的内存只是从一个特定的增量开始,这个增量是设备真正喜欢的字节数量的倍数。我的困惑是这行代码

// 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 =不适用于其他类型,如IntFloat等?

让我们先来谈谈为什么你想要对齐缓冲区,然后我们可以谈论按位算术。

我们的目标是分配一个金属缓冲区,可以存储我们的制服的三个(三缓冲)副本(以便我们可以在GPU读取另一个时写入缓冲区的一部分)。为了读取这三个副本中的每一个,我们在绑定缓冲区时提供一个偏移量,如currentBufferIndex * uniformsSize。某些金属设备需要这些偏移量为256的倍数,所以我们需要使用类似currentBufferIndex * alignedUniformsSize这样的偏移量。

我们如何“整理”一个整数到256的下一个最高倍数?我们可以通过删除“未对齐”大小的最低8位来有效地舍入,然后添加256,从而得到下一个最高倍数。向下取整部分是通过按位与逻辑1的补码(~)255来实现的,其中(32位)是0xFFFFFF00。向上舍入是通过加上0x100来完成的,即256。

有趣的是,如果基本大小已经对齐,则该技术无论如何都会虚假地舍入(例如,从256到512)。对于整数除法的代价,您可以避免这种浪费:

let alignedUniformsSize = ((MemoryLayout<Uniforms>.size + 255)/256) * 256 
+0

非常感谢这行,正常的算术版本更具可读性! – zsero