Swift中simd_packed向量的对齐(与Metal Shader语言相比)



我很难理解Swift中simd模块中的simd_packed向量。我用float4的例子,我希望有人能帮忙。

我的理解是simd_float4SIMD4< Float>typealiasMemoryLayout<SIMD4< Float>>.alignment = 16(字节(,因此是MemoryLayout<simd_float4>.alignment = 16。有道理。

但以下我不理解:simd_packed_float4也是SIMD4<Float>typealiasMemoryLayout<simd_packed_float4>.alignment = 16也是如此。

";包装的";在simd_packed_float4中,那么?";松弛排列";文件中提到的?

在Metal Shader语言规范(版本2.4(中(https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf)在表2.4(第28页(中,它说packed_float4的排列是4(这也是标量类型float的排列(,所以这是一个";松弛排列";(与16相比(。这本身是有道理的,但我如何将其与上述内容相协调(simd_packed_float4SIMD4<Float>MemoryLayout<simd_packed_float4> = 16的类型别名(?

事实上,我认为在Swift中用压缩类型实现这样的轻松对齐是不可能的。我认为Swift编译器无法将对齐属性带到实际的Swift接口中。

我认为这使得simd_packed_float4在Swift中毫无用处。

我做了一个操场来检查这个,按预期使用它是行不通的。

import simd
MemoryLayout<simd_float4>.stride
MemoryLayout<simd_packed_float4>.alignment
let capacity = 8
let buffer = UnsafeMutableBufferPointer<Float>.allocate(capacity: capacity)
for i in 0..<capacity {
buffer[i] = Float(i)
}
let rawBuffer = UnsafeMutableRawBufferPointer.init(buffer)
let readAligned = rawBuffer.load(fromByteOffset: MemoryLayout<Float>.stride * 4, as: simd_packed_float4.self)
print(readAligned)
let readUnaligned = rawBuffer.load(fromByteOffset: MemoryLayout<Float>.stride * 2, as: simd_packed_float4.self)
print(readUnaligned)

哪个将输出

SIMD4<Float>(4.0, 5.0, 6.0, 7.0)
Swift/UnsafeRawPointer.swift:900: Fatal error: load from misaligned raw pointer

如果你确实需要加载或将未对齐的simd_float4向量放入缓冲区,我建议你只做一个扩展,按组件进行扩展,这样所有的对齐都会成功,有点像这个

extension UnsafeMutableRawBufferPointer {
func loadFloat4(fromByteOffset offset: Int) -> simd_float4 {
let x = rawBuffer.load(fromByteOffset: offset + MemoryLayout<Float>.stride * 0, as: Float.self)
let y = rawBuffer.load(fromByteOffset: offset + MemoryLayout<Float>.stride * 1, as: Float.self)
let z = rawBuffer.load(fromByteOffset: offset + MemoryLayout<Float>.stride * 2, as: Float.self)
let w = rawBuffer.load(fromByteOffset: offset + MemoryLayout<Float>.stride * 3, as: Float.self)
return simd_float4(x, y, z, w)
}
}
let readUnaligned2 = rawBuffer.loadFloat4(fromByteOffset: MemoryLayout<Float>.stride * 2)
print(readUnaligned2)

或者你甚至可以让它成为通用

最新更新