首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift (vs Metal Shader language)中simd_packed矢量的对齐

Swift (vs Metal Shader language)中simd_packed矢量的对齐
EN

Stack Overflow用户
提问于 2021-06-12 05:49:12
回答 1查看 90关注 0票数 2

我很难理解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中“打包”的意义是什么呢?文档中提到的“轻松对齐”在哪里?

在金属着色器语言规范(版本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的类型别名)?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-12 11:39:42

实际上,我认为在Swift中不可能像这样轻松地与打包类型对齐。我认为Swift编译器不能将对齐属性带到实际的Swift接口。

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

我已经做了一个游乐场来检查这一点,并按计划使用它不起作用。

代码语言:javascript
复制
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)

它将输出以下内容

代码语言:javascript
复制
SIMD4<Float>(4.0, 5.0, 6.0, 7.0)
Swift/UnsafeRawPointer.swift:900: Fatal error: load from misaligned raw pointer

如果您确实需要加载未对齐的simd_float4向量或将其放入缓冲区中,我建议您只做一个扩展来完成此操作,因此所有的对齐都是这样的

代码语言:javascript
复制
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)

或者,您甚至可以使其泛型

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67943802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档