Descriptor Dynamic Offset
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)
Example
This example will have a 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, an 8 byte dynamic offset will be 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:
Example with VK_WHOLE_SIZE
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 bufferInfo = {
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