0

如果使用相同的推送常量范围创建两个管道布局,则它们被定义为“与推送常量兼容”。两个管道布局被定义为“与集合 N 兼容”,如果它们是用定义相同的描述符集合布局创建的,用于集合 0 到 N,并且如果它们是用相同的推送常量范围创建的。

vkCmdBindDescriptorSets 使编号为 [firstSet..firstSet+descriptorSetCount-1] 的集合使用存储在 pDescriptorSets[0..descriptorSetCount-1] 中的绑定用于后续渲染命令(根据 pipelineBindPoint 计算或图形)。以前通过这些集合应用的任何绑定都不再有效。

假设有两个流水线布局,第一个流水线布局包含一个集合#0,第二个流水线布局包含两个集合#0 #1。第一个集合0和第二个集合0是相同的描述符集布局。它们也有相同的推送常量范围,因此为上面的分布,两个流水线布局的set#0都兼容吗?</p>

// create set 0
...

VkDescriptorSetLayout setLayout0;
...
vkCreateDescriptorSetLayout(logicalDevice,
                            &layoutInfo,
                            nullptr,
                            &setLayout0);
...
VkDescriptorSet set0; 
VkDescriptorSetAllocateInfo allocInfo0 = {};
allocInfo0.descriptorSetCount = 1;
allocInfo0.pSetLayouts = &setLayout0;
...
vkAllocateDescriptorSets(logicalDevice,
                         &allocInfo0,
                         &set0);
...

// create first pipeline layout 
VkPipelineLayoutCreateInfo firstPipelineLayoutInfo = {};
firstPipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
firstPipelineLayoutInfo.setLayoutCount = 1;
firstPipelineLayoutInfo.pSetLayouts = &setLayout0;                           // <--- use set0


VkPipelineLayout firstPiplineLayout;
vkCreatePipelineLayout(logicalDevice,
                       &firstPipelineLayoutInfo,
                       nullptr,
                       &firstPiplineLayout);


// create set 1
...

VkDescriptorSetLayout setLayout1;
...
vkCreateDescriptorSetLayout(logicalDevice,
                            &layoutInfo,
                            nullptr,
                            &setLayout1);
...
VkDescriptorSet set1; 
VkDescriptorSetAllocateInfo allocInfo1 = {};
allocInfo1.descriptorSetCount = 1;
allocInfo1.pSetLayouts = &setLayout1;
...
vkAllocateDescriptorSets(logicalDevice,
                         &allocInfo1,
                         &set1);
...

// create second pipeline layout 
array<VkDescriptorSetLayout, 2> setLayout0And1 = {setLayout0, setLayout1} // <---use set0 set1

VkPipelineLayoutCreateInfo secondPipelineLayoutInfo = {};
secondPipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
secondPipelineLayoutInfo.setLayoutCount = 2;
secondPipelineLayoutInfo.pSetLayouts = &setLayout0And1;

VkPipelineLayout secondPiplineLayout;
vkCreatePipelineLayout(logicDevice,
                       &secondPipelineLayoutInfo,
                       nullptr,
                       &secondPiplineLayout);

// create pipeline
VkGraphicsPipelineCreateInfo pipelineInfo = {};
...
pipelineInfo.layout = secondPiplineLayout;

VkPipeline pipeline;
vkCreateGraphicsPipelines(logicDevice,
                          VK_NULL_HANDLE,
                          1,
                          &pipelineInfo,
                          nullptr,
                          &pipeline);

之后,在绘制时调用 vkCmdBindDescriptorSets 进行绑定。

...
vkCmdBindDescriptorSets(commandBuffer,
                        VK_PIPELINE_BIND_POINT_GRAPHICS,
                        firstPiplineLayout,
                        0,
                        1,
                        &set0,
                        0,
                        nullptr);

// When call vkCmdBindDescriptorSets with first set > 0 then the bound descriptor sets index [0 ... firstSet-1] will remain the same.
vkCmdBindDescriptorSets(commandBuffer,
                        VK_PIPELINE_BIND_POINT_GRAPHICS,
                        secondPiplineLayout,
                        1,
                        1,
                        &set1,
                        0,
                        nullptr);

vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
...
vkCmdDrawIndexed(commandBuffer,
                 indicesCount,
                 1, 0, 0, 0);
...

在该验证层之后:VkPipeline 0x42 使用 set #0 但该 set 未绑定。

为什么会出现错误?我哪里弄错了?

4

0 回答 0