【问题标题】:Pass an array within uniforms struct to Metal shader将制服结构中的数组传递给金属着色器
【发布时间】:2020-05-28 03:02:36
【问题描述】:

我在 Swift 中定义了一个 Uniforms 结构:

struct Uniforms {
    var t = Float(0.0)
    var arr = [0.2, 0.2, 0.2, 0.2, 0.2]
}

但是,我无法为其分配正确的MTLBuffer,因为MemoryLayout<Uniforms>.stride 返回16。这与 Swift 规范中关于 Array 是值类型的声明相矛盾。它实际上被MemoryLayout 视为引用类型。

长话短说,我如何将包含数组的 Uniforms 结构传递给着色器(我使用常量命名空间来传递它,一切都很好)。我是否需要通过单独的 [[buffer(n)]] 参数单独传递数组,我将从数组中复制内存?有更简单的选择吗?

【问题讨论】:

    标签: swift metal


    【解决方案1】:

    由于 Swift 对结构布局不做任何保证,直接将这种结构的内容复制到 Metal 缓冲区中是很危险的(另外,正如所写,该数组包含 Doubles,目前 Metal 不支持反正)。根据实际问题的形式,有几种不同的方法可行。

    如果您知道数组中元素的最大数量,您可以添加一个指示实际计数的结构成员,并使着色器期望的结构的最后一个元素成为一个固定长度的数组:

    #define MAX_VALUE_COUNT 1024
    struct ShaderUniforms {
        float t;
        uint32_t valueCount;
        float values[MAX_VALUE_COUNT];
    };
    

    然后,在 Swift 中,您可以分配一个最大大小的 Metal 缓冲区(在这种人为的情况下为 4104 字节)并将所需的任意数量的数组元素复制到缓冲区中(当然,在其他结构成员之前) .

    另外,是的,您可以使用指针类型的单独缓冲区参数(例如,constant float *values [[buffer(1)]])。这将允许您拥有一个不受任何显式编码到着色器中的内容限制的值计数。

    【讨论】:

    • 这很可悲(关于 Swift)。关于您对“常量浮点 * 值 [[buffer(1)]]”的评论 - 这不应该在着色器中通过引用来获取吗?谢谢
    • 另外根据这个问题/答案似乎 Swift current 可以为结构做出正确的布局:stackoverflow.com/questions/39302834/… - 这是否意味着我唯一的问题是在 Swift ,数组实际上不是一个值类型——我可以以某种方式制作所有存储在 Swift 结构中的数组值吗?如果没有数组,我认为currently使用structs应该没问题。
    • 如果你只是引用浮点数,你不能索引到它,我不知道你会如何将该类型写为对指针的引用。您可以想象将其键入为对固定长度数组的引用,甚至可能是可变长度数组,尽管其语法很粗俗。把它写成指针对我来说似乎很干净。
    • 我不知道您为什么选择依赖 Swift 的未指定行为。尽管顺序是有保证的,但我在规范中所知道的任何内容都没有说 Swift 不会在数组之前插入任意填充,也不会数组的第一个元素驻留在数组本身的地址处。如果您想保证布局,请在 (Objective-)C 中编写类型,您可以在其中控制布局和对齐,并将其桥接。
    • 可能是'常量数组 &values'?
    猜你喜欢
    • 2019-01-24
    • 2014-12-05
    • 2017-01-24
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    • 2021-01-07
    • 2014-10-04
    • 1970-01-01
    相关资源
    最近更新 更多