我正在尝试创建一个布局需要两个绑定,动态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个绑定布局的管道,但是创建每个描述符以仅填充每个绑定中的一个,然后为该管道的每个draw调用绑定两个描述符?
如果允许。这就是我创建管道和描述符的方式:
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);
}
答案 0 :(得分:1)
是的,您可以这样做。您的管道布局具有两个描述符集。两种描述符集布局中的每一个都有一个描述符:动态UBO和纹理。在绘制时,将每个描述符集布局的一个描述符集绑定到适当的集编号。
绑定纹理描述符集时,看来firstSet
参数是错误的:这是管道布局中的第二个集,因此它的索引为1
,但是您正在传递{{1} }。验证层应该警告您,您正在将描述符集与集布局绑定在一起,而集布局与该集的管线布局不符。
您不会显示访问这些着色器的代码,因此您可能已经这样做了。但是,当从单个描述符集转到两个描述符集时,您需要更新采样器绑定中的集合索引。