当前位置: 首页 > 知识库问答 >
问题:

Vulkan:一个管道和多个描述符集?

林鹏鹍
2023-03-14

我试图创建一个带有布局的单一管道,它需要两个绑定,一个动态UBO和一个图像/采样器绑定。我希望每个绑定都来自一个单独的描述符集,所以每次draw调用都会绑定两个描述符集。一个描述符集用于每个对象的纹理,另一个用于动态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个答案

艾子石
2023-03-14

是的,你能做到。管道布局有两个描述符集。两个描述符集布局中的每一个都有一个描述符:动态UBO和纹理。在绘制时,将每个描述符集布局的一个描述符集绑定到相应的集合编号。

绑定纹理描述符集时,firstSet参数似乎是错误的:这是管道布局中的第二个集,因此它具有索引1,但您正在传递0。验证层应该警告您,您将描述符集绑定到的集合布局与管道布局对该集合的预期不匹配。

您没有显示访问这些的着色器代码,所以您可能已经这样做了。但是当从单个描述符集到两个描述符集时,您需要更新采样器绑定中的集合索引。

 类似资料:
  • 问题内容: 我正在尝试将jenkins管道作为代码来做。我正在使用Github组织文件夹插件来扫描Github组织并为每个分支创建作业。有没有一种方法可以明确定义从Jenkinsfile获取的管道作业的名称?我还想为作业添加一些说明。 问题答案: 您需要使用如下所示。该部分很重要 编辑:上面一个重命名生成,其中原始问题是关于重命名作业。在管道中执行以下脚本可以做到这一点(这需要 适当的权限 )

  • 是否可以从另一个作业触发Jenkins多分支管道的立即扫描操作?我在将旧版本的Gitlab与Jenkins中的管道作业集成时遇到了某些问题,并遇到了这样的解决方法。 或者,现在可以使用notifyCommit web钩子触发扫描多分支管道吗? 这样做的目的是每当Git存储库中发生更改时扫描多分支管道,以便在这样的更改后检测到新的分支。另一个我无法以其他方式实现的目的(除了对我来说非常邪恶的每个分支

  • 问题内容: 使用posix的read()write()linux调用,可以确保如果我以串行方式通过一个文件描述符进行写入并通过另一个文件描述符进行读取,以使两个动作彼此互斥…读取文件描述符将始终看到写入文件描述符最后写入的内容? 我相信是这种情况,但我想确定一下,手册页对此没有太大帮助 问题答案: 这取决于您在哪里获得了两个文件描述符。如果它们来自dup(2)调用,则它们共享文件的偏移量和状态,因

  • 我们有一个Kafka主题,有源源不断的数据。为了处理它,我们有一个无状态的Flink管道,它使用该主题并写入另一个主题。 我们是不是漏掉了什么?我们误会什么了吗?有没有更好的解决办法? 谢了!

  • 目前,我们使用JJB编译Jenkins作业(大部分已经是管道),以便配置大约700个作业,但JJB2似乎无法很好地扩展以构建管道,我正在寻找一种方法将其从等式中删除。 我主要希望能够将所有这些管道存储在一个集中的存储库中。 请注意,在我们的用例中,将CI配置(jenkins文件)保存在每个存储库和分支中是不可能的,我们需要将所有管道保存在一个“jenkins jobs.git”repo中。