Настройка формата динамического буфера вершин в Vulkan - PullRequest
0 голосов
/ 26 октября 2018

В настоящее время мне поручено преобразовать базу кода OpenGL в Vulkan, но теперь я наткнулся на проблему с тем, как этот код использует вершинные буферы, потому что он очень динамически изменяет компоновку, чтобы обращаться к нему как к большому массиву кадров.

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

void SetupVertexBufferFormat(unsigned int frame1, unsigned int frame2)
{
    glVertexAttribPointer(PositionAttr, 3, GL_FLOAT, false, sizeof(Vertex), &vNull[frame1].x);
    glVertexAttribPointer(TexcoordAttr, 2, GL_FLOAT, false, sizeof(Vertex), &vNull[frame1].u);
    glVertexAttribPointer(Position2Attr, 3, GL_FLOAT, false, sizeof(Vertex), &vNull[frame2].x);
    glVertexAttribPointer(NormalAttr, 4, GL_INT_2_10_10_10_REV, true, sizeof(Vertex), &vNull[frame1].packedNormal);
    glVertexAttribPointer(Normal2Attr, 4, GL_INT_2_10_10_10_REV, true, sizeof(Vertex), &vNull[frame2].packedNormal);
}

Что хорошо и хорошоOpenGL, но в Vulkan макет буфера вершин является частью объекта конвейера!Это означает, что портирование установки потребует создания и уничтожения нескольких конвейеров на кадр, поскольку значения frame1 и frame2 могут быть почти случайно скомбинированы.

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

Есть ли способ обойти это или какой-то сложный конвейер управления единственная опция здесь?

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Чтобы расширить ответ Джерико.

Если вы используете отдельные атрибуты вершин из opengl, вы получите эту форму:

glVertexAttribFormat( PositionAttr,  3, GL_FLOAT, false, offsetof(Vertex, x));
glVertexAttribBinding(PositionAttr,  1);
glVertexAttribFormat( TexcoordAttr,  2, GL_FLOAT, false, offsetof(Vertex, u));
glVertexAttribBinding(TexcoordAttr,  1);
glVertexAttribFormat( NormalAttr,    4, GL_INT_2_10_10_10_REV, true, offsetof(Vertex, packedNormal));
glVertexAttribBinding(NormalAttr,    1);

glVertexAttribFormat( Position2Attr, 3, GL_FLOAT, false, offsetof(Vertex, x));
glVertexAttribBinding(Position2Attr, 2);
glVertexAttribFormat( Normal2Attr,   4, GL_INT_2_10_10_10_REV, true, offsetof(Vertex, packedNormal));
glVertexAttribBinding(Normal2Attr,   2);

Затем при рендеринге вы устанавливаете смещение для привязки 1 к смещению кадра 1 и для привязки 2 к смещению кадра 2.

void SetupVertexBufferFormat(unsigned int frame1, unsigned int frame2) {
    glBindVertexBuffer(1, vbo, &vNull[frame1], sizeof(Vertex));
    glBindVertexBuffer(2, vbo, &vNull[frame2], sizeof(Vertex));
}

Это вы можете напрямую перевести в состояние вулкана.

0 голосов
/ 26 октября 2018

Похоже, вы связываете формат вершин с привязками буфера вершин.glVertexAttrib объединяет оба в одном вызове, но у вас, кажется, есть единый согласованный формат вершин, который состоит из двух привязок, одна с 3 атрибутами, а вторая с 2 атрибутами.

Посмотрите некоторые уроки поРазделяйте форматы вершин в OpenGL и попробуйте рефакторинг вашего бэкэнда GL, чтобы использовать это.Эквивалентная настройка конвейера Vulkan должна стать более очевидной.

Привязка вершин Vulkan и описания атрибутов, которые соответствуют вызовам GL Ratchet, должны выглядеть следующим образом

std::vector<vk::VertexInputBindingDescription> bindingDescriptions = { 
    { 0, sizeof(Vertex), vk::VertexInputRate::eVertex },
    { 1, sizeof(Vertex), vk::VertexInputRate::eVertex }
};

std::vector<vk::VertexInputAttributeDescription> attributeDescriptions = {
    { PositionAttr, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, x) },
    { TexcoordAttr, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, u) },
    { NormalAttr, 0, vk::Format::eA2B10G10R10SnormPack32, offsetof(Vertex, packedNormal) },
    { Position2Attr, 1, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, x) },
    { Normal2Attr, 1, vk::Format::eA2B10G10R10SnormPack32, offsetof(Vertex, packedNormal) },
};
...