Настройка формата динамического буфера вершин в vulkan

В настоящее время мне поручено преобразовать базу кода 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.

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

1
0
965
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Кажется, вы объединяете формат вершин с привязками буфера вершин. 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) },
};

Чтобы расширить ответ JHerico.

Если вы используете отдельные атрибуты вершин из 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));
}

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

Другие вопросы по теме