Vulkanは、仕様で定義されているように、バインド時にオフセットを調整できる2種類のディスクリプタを提供しています。
-
動的ユニフォームバッファ (
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
) -
動的ストレージバッファ (
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
)
この例では、32 バイトのバッファを持ち、そのうち 16 バイトが vkUpdateDescriptorSets
の際に設定されます。この最初の例では、動的オフセットは追加しません。
VkDescriptorSet descriptorSet; // 割り当て
VkBuffer buffer; // 32 バイトのサイズ
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,
);
// 非動的オフセット
vkCmdBindDescriptorSets(
1, // descriptorSetCount,
&descriptorSet, // pDescriptorSets,
0, // dynamicOffsetCount
NULL // pDynamicOffsets
);
現在、バッファは以下のようになっています。
次に、バインド時に 8 バイトの動的オフセットを適用します。
uint32_t offsets[1] = { 8 };
vkCmdBindDescriptorSets(
1, // descriptorSetCount,
&descriptorSet, // pDescriptorSets,
1, // dynamicOffsetCount
offsets // pDynamicOffsets
);
現在、バッファは以下のようになっています。
今回は VK_WHOLE_SIZE
値を範囲に使用します。VkDescriptorBufferInfo::range
以外は、すべて上記の例と同じです。
VkDescriptorSet descriptorSet; // 割り当て
VkBuffer buffer; // 32 バイトのサイズ
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,
);
// 非動的オフセット
vkCmdBindDescriptorSets(
1, // descriptorSetCount,
&descriptorSet, // pDescriptorSets,
0, // dynamicOffsetCount
NULL // pDynamicOffsets
);
現在、バッファは以下のようになっています。
今回、動的オフセットを適用しようとすると、未定義の動作となり、検証レイヤでエラーが発生します。
// 無効
uint32_t offsets[1] = { 8 };
vkCmdBindDescriptorSets(
1, // descriptorSetCount,
&descriptorSet, // pDescriptorSets,
1, // dynamicOffsetCount
offsets // pDynamicOffsets
);
無効な動的オフセットの場合は、このようになります。