Skip to content

Latest commit

 

History

History
129 lines (97 loc) · 4.13 KB

descriptor_dynamic_offset.adoc

File metadata and controls

129 lines (97 loc) · 4.13 KB

ディスクリプタ動的オフセット

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
);

現在、バッファは以下のようになっています。

descriptor_dynamic_offset_example_a.png

次に、バインド時に 8 バイトの動的オフセットを適用します。

uint32_t offsets[1] = { 8 };
vkCmdBindDescriptorSets(
    1,              // descriptorSetCount,
    &descriptorSet, // pDescriptorSets,
    1,              // dynamicOffsetCount
    offsets         // pDynamicOffsets
);

現在、バッファは以下のようになっています。

descriptor_dynamic_offset_example_b.png

VK_WHOLE_SIZE を使用した例

今回は 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
);

現在、バッファは以下のようになっています。

descriptor_dynamic_offset_example_c.png

今回、動的オフセットを適用しようとすると、未定義の動作となり、検証レイヤでエラーが発生します。

// 無効
uint32_t offsets[1] = { 8 };
vkCmdBindDescriptorSets(
    1,              // descriptorSetCount,
    &descriptorSet, // pDescriptorSets,
    1,              // dynamicOffsetCount
    offsets         // pDynamicOffsets
);

無効な動的オフセットの場合は、このようになります。

descriptor_dynamic_offset_example_d.png

制限

また、minUniformBufferOffsetAlignmentminStorageBufferOffsetAlignment も確認することが重要です。ベースオフセットと動的オフセットの両方がこれらの制限の倍数でなければならないからです。