Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/107.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS金属缓冲区不符合步幅值_Ios_Metal - Fatal编程技术网

iOS金属缓冲区不符合步幅值

iOS金属缓冲区不符合步幅值,ios,metal,Ios,Metal,我有一个每个实例的统一缓冲区,其中缓冲区中的每个元素都是64字节,但我只使用顶点着色器中每个元素的前16个字节(float3)。我迈了一大步来描述这一点。问题是它不会跨越其他48个字节,除非在着色器中向结构添加填充,使其也为64个字节 // Particle Instance Position vertexDescriptor.attributes[2].format = .Float3 // 16 bytes with padding. vertexDescriptor.attr

我有一个每个实例的统一缓冲区,其中缓冲区中的每个元素都是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)
应用程序端粒子结构:

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
    }
}
这是相应的金属结构,即
粒子。位置
对应于着色器中的
InstanceUniforms.instanceTranslate
。我希望上面的步幅设置意味着每个实例都会加载
粒子。位置
,缓冲区中每个
粒子的其他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
,就像它只跨过
InstanceUniforms
结构的大小一样,而不管在顶点描述符中设置的跨步是什么


我确信我一定是做错了什么,看起来你不需要填充你的着色器结构。

所以看起来就是这样™ 使用金属缓冲区:必须填充着色器结构以匹配应用程序结构的步幅。我认为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
Swift:

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