Вулкан: один конвейер и несколько наборов дескрипторов? - PullRequest
1 голос
/ 03 июня 2019

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


commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);

for (int ii = 0; ii < mActiveQuads; ii++)
{
    uint32_t dynamicOffset = ii * static_cast<uint32_t>(dynamicAlignment);

    // bind texture for this quad
    commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, sharedPipelineLayout, 0, 1,
            &swapResources[current_buffer].textureDescriptors[ii], 1, &dynamicOffset);

    // draw the dynamic UBO with offset for this quad
    commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, sharedPipelineLayout, 0, 1,
                &swapResources[current_buffer].quadDescriptor, 1, &dynamicOffset);

    commandBuffer.draw(2 * 3, 1, 0, 0);
}

Но, похоже, это не работает. Прежде всего, я не уверен, что понял все о наборах дескрипторов и схемах конвейера, чтобы знать, разрешено ли то, что я делаю. Имеет ли это смысл? Что я могу создать конвейер с макетом привязки 2, но создать каждый дескриптор, чтобы заполнить только одну из этих привязок каждый, а затем связать два дескриптора для каждого вызова отрисовки для этого конвейера?

Если это разрешено. Вот как я создаю конвейер и дескрипторы:

vk::DescriptorSetLayoutBinding const layout_bindings[2] = { vk::DescriptorSetLayoutBinding()
        .setBinding(0)
        .setDescriptorType(vk::DescriptorType::eUniformBufferDynamic)
        .setDescriptorCount(1)
        .setStageFlags(vk::ShaderStageFlagBits::eVertex)
        .setPImmutableSamplers(nullptr),
        vk::DescriptorSetLayoutBinding()
        .setBinding(1)
        .setDescriptorType(vk::DescriptorType::eCombinedImageSampler)
        .setDescriptorCount(1)//texture_count)
        .setStageFlags(vk::ShaderStageFlagBits::eFragment)
        .setPImmutableSamplers(nullptr) };


    // note binding count is 1 here
    auto const descriptor_layout = vk::DescriptorSetLayoutCreateInfo().setBindingCount(1).setPBindings(&layout_bindings[0]); // using the first part of the above layout
    device.createDescriptorSetLayout(&descriptor_layout, nullptr, &quadDescriptorLayout);

    // note binding count is 1 here
    auto const descriptor_layout2 = vk::DescriptorSetLayoutCreateInfo().setBindingCount(1).setPBindings(&layout_bindings[1]); // using the second part of the above layout
    device.createDescriptorSetLayout(&descriptor_layout2, nullptr, &textureDescriptorLayout);

    // Now create the pipeline, note we use both the bindings above with
    // layout count = 2
    auto const pPipelineLayoutCreateInfo = vk::PipelineLayoutCreateInfo().setSetLayoutCount(2).setPSetLayouts(desc_layout);
    device.createPipelineLayout(&pPipelineLayoutCreateInfo, nullptr, &sharedPipelineLayout);

и сами дескрипторы:

    // alloc quad descriptor
    alloc_info =
        vk::DescriptorSetAllocateInfo()
            .setDescriptorPool(desc_pool)
            .setDescriptorSetCount(1)
            .setPSetLayouts(&quadDescriptorLayout);


     // texture descriptors(multiple descriptors, one per quad object)
    alloc_info =
        vk::DescriptorSetAllocateInfo()
            .setDescriptorPool(desc_pool)
            .setDescriptorSetCount(1)
            .setPSetLayouts(&textureDescriptorLayout);

Раньше, когда текстура и UBO в одном наборе дескрипторов работали нормально, я мог видеть несколько четырехугольников, но все они использовали одну текстуру. Когда я разделяю текстуры на другой набор дескрипторов, тогда я получаю зависшее приложение. При попытке отправить графическую очередь я получаю сообщение об ошибке «устройство потеряно».

Любое понимание того, возможно ли это сделать или что я делаю что-то не так в моей настройке, будет очень признательно. Большое спасибо!

Ниже добавлен код шейдера:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform UniformBufferObject {
    mat4 mvp;
    vec4 position[6];
    vec4 attr[6];
} ubo;


layout(location = 0) out vec2 fragTexCoord;

void main() {
    gl_Position = ubo.mvp *ubo.position[gl_VertexIndex];
    fragTexCoord = vec2(ubo.attr[gl_VertexIndex].x, ubo.attr[gl_VertexIndex].y);
}

Пиксельный шейдер:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(set=0, binding = 1) uniform sampler2D texSampler;

layout(location = 0) in vec2 fragTexCoord;

layout(location = 0) out vec4 outColor;

void main() {
    outColor = texture(texSampler, fragTexCoord);
}

1 Ответ

1 голос
/ 03 июня 2019

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

Похоже, параметр firstSet при неправильной привязке набора дескрипторов текстуры: это второй набор в конвейеремакет, поэтому он имеет индекс 1, но вы передаете 0.Слои проверки должны были предупредить вас, что вы связываете набор дескрипторов с макетом набора, который не соответствует тому, что макет конвейера ожидает для этого набора.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...