Vulkan offers two types of descriptors that allow adjusting the offset at bind time as defined in the spec.
-
dynamic uniform buffer (
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
) -
dynamic storage buffer (
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
)
This example will have buffer of 32 bytes and 16 of the bytes will be set at vkUpdateDescriptorSets
time. In this first example, we will not add any dynamic offset.
VkDescriptorSet descriptorSet; // allocated
VkBuffer buffer; // size of 32 bytes
VkDescriptorBufferInfo bufferInfo = {
buffer,
4, // offset
16 // range
};
VkWriteDescriptorSet writeInfo = {
.dstSet = descriptorSet,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
.pBufferInfo = bufferInfo
};
vkUpdateDescriptorSets(
1, // descriptorWriteCount,
&writeInfo // pDescriptorWrites,
);
// No dynamic offset
vkCmdBindDescriptorSets(
1, // descriptorSetCount,
&descriptorSet, // pDescriptorSets,
0, // dynamicOffsetCount
NULL // pDynamicOffsets
);
Our buffer now currently looks like the following:
Next, a 8 byte dynamic offset will applied at bind time.
uint32_t offsets[1] = { 8 };
vkCmdBindDescriptorSets(
1, // descriptorSetCount,
&descriptorSet, // pDescriptorSets,
1, // dynamicOffsetCount
offsets // pDynamicOffsets
);
Our buffer currently looks like the following:
This time the VK_WHOLE_SIZE
value will be used for the range. Everything looks the same as the above example except the VkDescriptorBufferInfo::range
VkDescriptorSet descriptorSet; // allocated
VkBuffer buffer; // size of 32 bytes
VkDescriptorBufferInfo info = {
buffer,
4, // offset
VK_WHOLE_SIZE // range
};
VkWriteDescriptorSet writeInfo = {
.dstSet = descriptorSet,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
.pBufferInfo = bufferInfo
};
vkUpdateDescriptorSets(
1, // descriptorWriteCount,
&writeInfo // pDescriptorWrites,
);
// No dynamic offset
vkCmdBindDescriptorSets(
1, // descriptorSetCount,
&descriptorSet, // pDescriptorSets,
0, // dynamicOffsetCount
NULL // pDynamicOffsets
);
Our buffer currently looks like the following:
This time, if we attempt to apply a dynamic offset it will be met with undefined behavior and the validation layers will give an error
// Invalid
uint32_t offsets[1] = { 8 };
vkCmdBindDescriptorSets(
1, // descriptorSetCount,
&descriptorSet, // pDescriptorSets,
1, // dynamicOffsetCount
offsets // pDynamicOffsets
);
This is what it looks like with the invalid dynamic offset