Skip to content

Commit 1a45b1a

Browse files
committed
Avoid binding descriptor sets for layouts without that set
Avoids disturbing necessary descriptor sets while still avoiding the need for full layout compatibility checks. This is achieved with a basic vector<bool> saying which sets a pipeline layout has and doesn't have, so layouts it doesn't have won't be bound. This could mean different sets are bound than if a full compatibility check was done, but that should only happen when the scenegraph requested invalid API usage - there should only be one BindDescriptorSet for each slot at the top of the state stacks, and if it's for a slot the current pipeline layout needs, it must be compatible. Therefore, we only need to worry about compatibility checks for slots the current pipeline layout doesn't use.
1 parent 8e575d7 commit 1a45b1a

6 files changed

Lines changed: 27 additions & 6 deletions

File tree

include/vsg/state/PipelineLayout.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace vsg
3434
VkPipelineLayoutCreateFlags flags = 0;
3535
DescriptorSetLayouts setLayouts;
3636
PushConstantRanges pushConstantRanges;
37+
std::vector<bool> descriptorSetSlots;
3738

3839
/// Vulkan VkPipelineLayout handle
3940
VkPipelineLayout vk(uint32_t deviceID) const { return _implementation[deviceID]->_pipelineLayout; }

include/vsg/vk/CommandBuffer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ namespace vsg
5656
void setCurrentPipelineLayout(const PipelineLayout* pipelineLayout);
5757

5858
VkPipelineLayout getCurrentPipelineLayout() const { return _currentPipelineLayout; }
59+
const std::vector<bool>& getCurrentDescriptorSetSlots() const { return _currentDescriptorSetSlots; }
5960
VkShaderStageFlags getCurrentPushConstantStageFlags() const { return _currentPushConstantStageFlags; }
6061

6162
ref_ptr<ScratchMemory> scratchMemory;
@@ -73,6 +74,7 @@ namespace vsg
7374
ref_ptr<Device> _device;
7475
ref_ptr<CommandPool> _commandPool;
7576
VkPipelineLayout _currentPipelineLayout;
77+
std::vector<bool> _currentDescriptorSetSlots;
7678
VkShaderStageFlags _currentPushConstantStageFlags;
7779
};
7880
VSG_type_name(vsg::CommandBuffer);

src/vsg/state/BindDescriptorSet.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ void BindDescriptorSets::compile(Context& context)
113113
void BindDescriptorSets::record(CommandBuffer& commandBuffer) const
114114
{
115115
//info("BindDescriptorSets::record() ", dynamicOffsets.size(), ", ", dynamicOffsets.data());
116+
if (commandBuffer.getCurrentDescriptorSetSlots().size() < firstSet + descriptorSets.size())
117+
return;
118+
for (size_t slot = firstSet; slot < firstSet + descriptorSets.size(); ++slot)
119+
{
120+
if (!commandBuffer.getCurrentDescriptorSetSlots()[slot])
121+
return;
122+
}
116123
auto& vkd = _vulkanData[commandBuffer.deviceID];
117124
vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, vkd._vkPipelineLayout, firstSet,
118125
static_cast<uint32_t>(vkd._vkDescriptorSets.size()), vkd._vkDescriptorSets.data(),
@@ -209,8 +216,11 @@ void BindDescriptorSet::compile(Context& context)
209216
void BindDescriptorSet::record(CommandBuffer& commandBuffer) const
210217
{
211218
//info("BindDescriptorSet::record() ", dynamicOffsets.size(), ", ", dynamicOffsets.data());
212-
auto& vkd = _vulkanData[commandBuffer.deviceID];
213-
vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, vkd._vkPipelineLayout, firstSet,
214-
1, &(vkd._vkDescriptorSet),
215-
static_cast<uint32_t>(dynamicOffsets.size()), dynamicOffsets.data());
219+
if (commandBuffer.getCurrentDescriptorSetSlots().size() > firstSet && commandBuffer.getCurrentDescriptorSetSlots()[firstSet])
220+
{
221+
auto& vkd = _vulkanData[commandBuffer.deviceID];
222+
vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, vkd._vkPipelineLayout, firstSet,
223+
1, &(vkd._vkDescriptorSet),
224+
static_cast<uint32_t>(dynamicOffsets.size()), dynamicOffsets.data());
225+
}
216226
}

src/vsg/state/PipelineLayout.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ PipelineLayout::PipelineLayout(const PipelineLayout& rhs, const CopyOp& copyop)
3030
Inherit(rhs, copyop),
3131
flags(rhs.flags),
3232
setLayouts(rhs.setLayouts),
33-
pushConstantRanges(rhs.pushConstantRanges)
33+
pushConstantRanges(rhs.pushConstantRanges),
34+
descriptorSetSlots(rhs.descriptorSetSlots)
3435
{
3536
}
3637

@@ -123,9 +124,13 @@ void PipelineLayout::compile(Context& context)
123124
{
124125
if (!_implementation[context.deviceID])
125126
{
127+
descriptorSetSlots.clear();
128+
descriptorSetSlots.reserve(setLayouts.size());
129+
126130
for (auto dsl : setLayouts)
127131
{
128132
if (dsl) dsl->compile(context);
133+
descriptorSetSlots.push_back(dsl != nullptr);
129134
}
130135
_implementation[context.deviceID] = PipelineLayout::Implementation::create(context.device, setLayouts, pushConstantRanges, flags);
131136
}

src/vsg/state/ViewDependentState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ void BindViewDescriptorSets::compile(Context& context)
151151

152152
void BindViewDescriptorSets::record(CommandBuffer& commandBuffer) const
153153
{
154-
if (commandBuffer.viewDependentState)
154+
if (commandBuffer.viewDependentState && commandBuffer.getCurrentDescriptorSetSlots().size() > firstSet && commandBuffer.getCurrentDescriptorSetSlots()[firstSet])
155155
{
156156
commandBuffer.viewDependentState->bindDescriptorSets(commandBuffer, pipelineBindPoint, layout->vk(commandBuffer.deviceID), firstSet);
157157
}

src/vsg/vk/CommandBuffer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ CommandBuffer::CommandBuffer(CommandPool* commandPool, VkCommandBuffer commandBu
3030
_device(commandPool->getDevice()),
3131
_commandPool(commandPool),
3232
_currentPipelineLayout(VK_NULL_HANDLE),
33+
_currentDescriptorSetSlots(),
3334
_currentPushConstantStageFlags(0)
3435
{
3536
}
@@ -45,6 +46,7 @@ CommandBuffer::~CommandBuffer()
4546
void CommandBuffer::reset()
4647
{
4748
_currentPipelineLayout = VK_NULL_HANDLE;
49+
_currentDescriptorSetSlots.clear();
4850
_currentPushConstantStageFlags = 0;
4951

5052
_commandPool->reset();
@@ -59,6 +61,7 @@ void CommandBuffer::setCurrentPipelineLayout(const PipelineLayout* pipelineLayou
5961
state->dirtyStateStacks();
6062

6163
_currentPipelineLayout = newLayout;
64+
_currentDescriptorSetSlots = pipelineLayout->descriptorSetSlots;
6265
if (pipelineLayout->pushConstantRanges.empty())
6366
_currentPushConstantStageFlags = 0;
6467
else

0 commit comments

Comments
 (0)