iOS Metal缓冲区不符合步幅值

时间:2015-10-22 21:22:06

标签: ios metal

我有一个每实例的统一缓冲区,其中缓冲区中的每个元素都是64字节,但我只使用顶点着色器中每个元素的前16个字节(float3)。我把步伐向上描述了这一点。问题是它没有跨越其他48个字节,除非我在着色器中向结构添加填充,这样它也是64个字节。

// Particle Instance Position
vertexDescriptor.attributes[2].format = .Float3   // 16 bytes with padding.     
vertexDescriptor.attributes[2].offset = 0
vertexDescriptor.attributes[2].bufferIndex = 2
vertexDescriptor.layouts[2].stride = strideof(Particle)
vertexDescriptor.layouts[2].stepFunction = .PerInstance

...

commandEncoder.setVertexBuffer(instanceUniformBuffer, offset:0, atIndex:2)

App侧粒子结构:

struct Particle {

    var position = float3()
    var prevPos = float3()
    var attractPoint = float3()

    var ref: DataRef!
    var state = State.Free

    enum State: Int {
        case Free = 0
        case Active
    }
}

这里是相应的Metal结构,即Particle.position对应着色器中的InstanceUniforms.instanceTranslate。我希望上面的步幅设置意味着每个实例加载Particle.position,并跳过缓冲区中每个Particle的其他48个字节。

struct InstanceUniforms
{
    float3 instanceTranslate [[ attribute(2) ]];
};

一些健全性检查,一切都有道理:

sizeof(float3) 16
alignof(float3) 16
sizeof(Particle) 57
alignof(Particle) 16
strideof(Particle) 64

但除非我将着色器结构填充到64字节,否则它不起作用:

struct InstanceUniforms
{
    float3 instanceTranslate [[ attribute(2) ]];
    float4 pad[3];
};

否则对于第二个实例,着色器实际上将instanceTranslate设置为缓冲区中第一个元素的Particle.prevPos,就像它只跨越{{的大小一样1}} struct,不管顶点描述符中的步幅是什么。

我确定我必须在这里做错事,看起来你不应该填充你的着色器结构。

1 个答案:

答案 0 :(得分:2)

所以看起来这只是带有金属缓冲区的The Way It Is™:你必须填充着色器结构以匹配app结构的步幅。我不认为Metal shader运行时很难从缓冲区加载 stride 字节并转换第一个 sizeof(MyShaderStruct) 他们。或者在附加管道状态时自动加载结构。但这些便利可能会产生效率。

这是我的Swift / Shader结构现在的样子供参考:

<强>金属:

struct Particle
{
   float3 position;
   float3 prevPos;
   float4 color;
   float4 lineColor;
   float  scale;
   char   pad[60];
};

<强>夫特:

struct Particle {
    var position = float3()
    var prevPos = float3()
    var color = float4()
    var lineColor = float4()
    var scale:Float = 0
    var gravity = float3()

    var data: DataRef!
    weak var physics: Physics? = nil
    var state = State.Free

    enum State: Int {
        case Free = 0
        case Active
    }
}

sizeof(Particle) 113
alignof(Particle) 16
strideof(Particle) 128