繁体   English   中英

Swift 中 simd_packed 向量的 Alignment(与金属着色器语言相比)

[英]Alignment of simd_packed vector in Swift (vs Metal Shader language)

我无法理解 Swift 中 simd 模块中有关 simd_packed 向量的一些内容。 我用float4的例子,希望有人能帮忙。

我的理解是simd_float4typealias SIMD4< Float>MemoryLayout<SIMD4< Float>>.alignment = 16 (字节)的类型别名,因此MemoryLayout<simd_float4>.alignment = 16 说得通。

但以下我不明白: simd_packed_float4也是typealias SIMD4<Float>的类型别名。 所以MemoryLayout<simd_packed_float4>.alignment = 16

那么simd_packed_float4中的“打包”有什么意义呢? 文档所说的“宽松对齐”在哪里?

In the Metal Shader Language Specification (Version 2.4) ( https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf ) in Table 2.4 (p.28), it says the alignment of packed_float4 is 4 (这也是标量类型的 alignment,float),所以这是一个“宽松的对齐方式”(与 16 相比)。 这本身是有道理的,但是我如何将其与上述内容相协调( simd_packed_float4SIMD4<Float>MemoryLayout<simd_packed_float4> = 16的类型别名)?

我实际上认为用 Swift 中的打包类型来实现像这样的轻松 alignment 是不可能的。 我认为 Swift 编译器无法将 alignment 属性带入实际的 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)

哪个会 output

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)

或者你甚至可以让它通用

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM