如果使用相同的推送常量范围创建两个管道布局,则它们被定义为“与推送常量兼容”。两个管道布局被定义为“与集合 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 未绑定。
为什么会出现错误?我哪里弄错了?