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