Смещение атрибута второго буфера металлического шейдера не работает - PullRequest
1 голос
/ 23 июня 2019

Я пытаюсь визуализировать сетку с дополнительным атрибутом, присутствующим в данных вершины, но я замечаю, что значение смещения, которое я установил в дескрипторе вершины для этого атрибута, похоже, не соблюдается. Он действует так, как будто смещение равно нулю, поэтому извлекает значения вершин вместо данных, которые я ищу.

Мои данные вершин определены так:

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 голосов
/ 23 июня 2019

Кажется, что ModelIO ожидает, что атрибуты дескриптора вершины будут иметь имена, совпадающие с именами полей, которые используются в структуре буфера вершин для приведенного выше сценария.Я исправил это так:

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

После прикрепления имен к каждому атрибуту шейдер загрузил правильные данные.

Мне удалось найти эту информацию через случайный запуск.с заголовком, который объявляет метод MTKModelIOVertexDescriptorFromMetal.Требование упомянуто в конце:

Этот метод может только установить формат вершины, смещение, bufferIndex и информацию о шаге в произведенном дескрипторе вершины ввода / вывода модели.Он не добавляет никакой семантической информации, такой как имена атрибутов. Имена должны быть заданы в возвращенном дескрипторе вершины ввода-вывода модели, прежде чем он может быть применен к сетке ввода-вывода модели.

...