金属着色器的第二个缓冲区属性偏移量不起作用

时间:2019-06-23 12:14:46

标签: metal

我正在尝试渲染一个顶点数据中存在附加属性的网格,但是我注意到在顶点描述符中为此属性设置的偏移值似乎没有受到尊重。它的行为就像偏移量为零,因此提取顶点值而不是我要查找的数据。

我的顶点数据的定义如下:

vertices      metadata
0, 1, 0, 1,   1, 0,
0, 1, 0, 0,   4, 0,

在着色器中,我将其像这样拉入:

typedef struct {
  float4 data [[attribute(0)]];
  float2 index [[attribute(1)]];
} Vertex;

vertex ColorInOut vertexShader(Vertex in [[stage_in]], 
                  constant VertexShaderUniforms & u [[ buffer(2) ]]) {...}

然后我要设置顶点描述符以处理这种格式:

auto _mtlVertexDescriptor = [[MTLVertexDescriptor alloc] init];

_mtlVertexDescriptor.attributes[0].format = MTLVertexFormatFloat4;
_mtlVertexDescriptor.attributes[0].offset = 0;
_mtlVertexDescriptor.attributes[0].bufferIndex = 0;

_mtlVertexDescriptor.attributes[1].format = MTLVertexFormatFloat2;
_mtlVertexDescriptor.attributes[1].offset = sizeof(vector_float4);
_mtlVertexDescriptor.attributes[1].bufferIndex = 0;

_mtlVertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
_mtlVertexDescriptor.layouts[0].stepRate = 1;
_mtlVertexDescriptor.layouts[0].stride = sizeof(vector_float4) + sizeof(vector_float2);

在Metal调试器中,我注意到,而不是上面的数据条目,而是在Geometry查看器中看到以下输出:

vertices      metadata
0, 1, 0, 1,   0, 1,
0, 1, 0, 0,   0, 1,

在这种情况下可能很重要,我应该指出,当我将其作为应用程序的额外渲染选项插入时,我会手动加载模型,我将通过以下方式进行此操作:

std::vector<float> vertices = {...};
auto allocator = [[MTKMeshBufferAllocator alloc] initWithDevice:device];
auto vertexData = [NSData dataWithBytes: vertices.data() length:vertices.size() * sizeof(float)];
auto vertexBuffer = [allocator newBufferWithData:vertexData type:MDLMeshBufferTypeVertex];

auto mdlVertexDescriptor = MTKModelIOVertexDescriptorFromMetal(vertexDescriptor);
// For this particlular example, `row_size` is 6, corresponding to the number of values in each vertex
auto mdlMesh = [[MDLMesh alloc] initWithVertexBuffer:vertexBuffer vertexCount:vertices.size() / row_size descriptor:mdlVertexDescriptor submeshes:@[]];
mdlMesh.vertexDescriptor = mdlVertexDescriptor;

NSError* error = nil;
auto m = [[MTKMesh alloc] initWithMesh:mdlMesh
                              device:device
                               error:&error];

为了使偏移正确应用,我是否缺少任何魔术调用?

[编辑]

我已经验证了顶点缓冲区对象本身中存在相同的问题。我已经确认传递到MTKModelIOVertexDescriptorFromMetal调用中的顶点描述符是预期的描述符,并且我还确认了NSData对象中的原始数据与std :: vector值相同,因此问题是可能取决于我与MDLMesh的互动方式。

1 个答案:

答案 0 :(得分:0)

似乎ModelIO希望顶点描述符属性都具有与上述场景中顶点缓冲结构中使用的字段名称匹配的名称。我这样修复:

vertexDescriptor.attributes[0].name = @"data";
vertexDescriptor.attributes[1].name = @"index";

将名称附加到每个属性后,着色器将加载正确的数据。

我设法通过带有声明MTKModelIOVertexDescriptorFromMetal方法的标头的随机机会插入找到了这些信息。最后提到了该要求:

  

此方法只能在产生的Model I / O顶点描述符中设置顶点格式,偏移量,bufferIndex和步幅信息。它不添加任何语义信息,例如属性名称。 必须先在返回的模型I / O顶点描述符中设置名称,然后才能将其应用于模型I / O网格。