|
| 1 | +// Copyright 2025 The Khronos Group, Inc. |
| 2 | +// SPDX-License-Identifier: CC-BY-4.0 |
| 3 | + |
| 4 | +ifndef::chapters[:chapters:] |
| 5 | +ifndef::images[:images: images/] |
| 6 | + |
| 7 | +[[descriptor-arrays]] |
| 8 | += Descriptor Arrays |
| 9 | + |
| 10 | +This chapter is to help explain about how you can create an array of descriptors. |
| 11 | + |
| 12 | +== Bindings vs Arrays |
| 13 | + |
| 14 | +Inside a single descriptor set there can be multiple bindings. The main advantage of bindings is if you have different types of descriptors in the descriptor set (samplers, uniform buffers, etc). |
| 15 | + |
| 16 | +When you have multiple of the same descriptor type, you might want to use an array of descriptors instead. |
| 17 | + |
| 18 | +As a simple example, if we have 4 `VkBuffer` that we want to turn into 4 different Uniform Buffers, we could represent this as 4 different bindings in the descriptor set: |
| 19 | + |
| 20 | +[source,glsl] |
| 21 | +---- |
| 22 | +layout(set = 0, binding = 0) uniform UBO0 { |
| 23 | + uint data_0; |
| 24 | +}; |
| 25 | +layout(set = 0, binding = 1) uniform UBO1 { |
| 26 | + uint data_1; |
| 27 | +}; |
| 28 | +layout(set = 0, binding = 2) uniform UBO2 { |
| 29 | + uint data_2; |
| 30 | +}; |
| 31 | +layout(set = 0, binding = 3) uniform UBO3 { |
| 32 | + uint data_3; |
| 33 | +}; |
| 34 | +---- |
| 35 | + |
| 36 | +We could also represent this as an array of 4 descriptors: |
| 37 | + |
| 38 | +[source,glsl] |
| 39 | +---- |
| 40 | +layout(set = 0, binding = 0) uniform UBO0 { |
| 41 | + uint data; |
| 42 | +} buffers[4]; |
| 43 | +---- |
| 44 | + |
| 45 | +If you have the `runtimeDescriptorArray` feature found in xref:{chapters}extensions/VK_EXT_descriptor_indexing.adoc[VK_EXT_descriptor_indexing] you can also tell the shader the array size will be known at runtime |
| 46 | + |
| 47 | +[source,glsl] |
| 48 | +---- |
| 49 | +layout(set = 0, binding = 0) uniform UBO0 { |
| 50 | + uint data; |
| 51 | +} buffers[]; |
| 52 | +---- |
| 53 | + |
| 54 | +== Setting up a Descriptor Array |
| 55 | + |
| 56 | +Using the example of |
| 57 | + |
| 58 | +[source,glsl] |
| 59 | +---- |
| 60 | +layout(set = 0, binding = 0) uniform UBO0 { |
| 61 | + uint data; |
| 62 | +} buffers[4]; |
| 63 | +---- |
| 64 | + |
| 65 | +it is pretty easy to set up. You just need to set your `VkDescriptorSetLayoutBinding::descriptorCount` to `4`. |
| 66 | + |
| 67 | +When you update you have 2 options |
| 68 | + |
| 69 | +1. Use an array of 4 `VkDescriptorBufferInfo` (likely easier way) |
| 70 | + |
| 71 | +[source,c++] |
| 72 | +---- |
| 73 | +VkDescriptorBufferInfo buffer_infos[4]; |
| 74 | +buffer_infos[0] = {buffer_0, 0, VK_WHOLE_SIZE}; |
| 75 | +buffer_infos[1] = {buffer_1, 0, VK_WHOLE_SIZE}; |
| 76 | +buffer_infos[2] = {buffer_2, 0, VK_WHOLE_SIZE}; |
| 77 | +buffer_infos[3] = {buffer_3, 0, VK_WHOLE_SIZE}; |
| 78 | +
|
| 79 | +VkWriteDescriptorSet writes; |
| 80 | +writes.dstBinding = 0; |
| 81 | +writes.dstArrayElement = 0; |
| 82 | +writes.descriptorCount = 4; // will consume 4 items in pBufferInfo |
| 83 | +writes.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; |
| 84 | +writes.pBufferInfo = buffer_infos; |
| 85 | +---- |
| 86 | + |
| 87 | +2. Use an array of 4 `VkWriteDescriptorSet` |
| 88 | + |
| 89 | +[source,c++] |
| 90 | +---- |
| 91 | +VkWriteDescriptorSet writes[4]; |
| 92 | +writes[0].dstArrayElement = 0; // points which descriptor in the array |
| 93 | +writes[0].descriptorCount = 1; |
| 94 | +writes[0].pBufferInfo = buffer_info_0; |
| 95 | +
|
| 96 | +writes[1].dstArrayElement = 1; |
| 97 | +writes[1].descriptorCount = 1; |
| 98 | +writes[1].pBufferInfo = buffer_info_1; |
| 99 | +
|
| 100 | +writes[2].dstArrayElement = 2; |
| 101 | +writes[2].descriptorCount = 1; |
| 102 | +writes[2].pBufferInfo = buffer_info_2; |
| 103 | +
|
| 104 | +writes[3].dstArrayElement = 3; |
| 105 | +writes[3].descriptorCount = 1; |
| 106 | +writes[3].pBufferInfo = buffer_info_3; |
| 107 | +---- |
| 108 | + |
| 109 | +== Consecutive Binding Updates |
| 110 | + |
| 111 | +When updating multiple bindings at once there is a concept of link:https://docs.vulkan.org/spec/latest/chapters/descriptorsets.html#descriptorsets-updates-consecutive[Consecutive Binding Updates in the Vulkan Spec]. |
| 112 | + |
| 113 | +The follow is an example to help illustrate how it works. We will have 5 descriptors spread across for 3 different bindings. The shader code is expressed as: |
| 114 | + |
| 115 | +[source,glsl] |
| 116 | +---- |
| 117 | +layout(set = 0, binding = 1) uniform sampler Samplers_A[2]; |
| 118 | +
|
| 119 | +layout(set = 0, binding = 2) uniform sampler Samplers_B; |
| 120 | +
|
| 121 | +layout(set = 0, binding = 6) uniform sampler Samplers_C[2]; |
| 122 | +---- |
| 123 | + |
| 124 | +The API is expressed as: |
| 125 | + |
| 126 | +[source,c++] |
| 127 | +---- |
| 128 | +VkDescriptorSetLayoutBinding sampler_a; |
| 129 | +sampler_a.binding = 1; |
| 130 | +sampler_a.descriptorCount = 2; |
| 131 | +
|
| 132 | +VkDescriptorSetLayoutBinding sampler_b; |
| 133 | +sampler_b.binding = 2; |
| 134 | +sampler_b.descriptorCount = 1; |
| 135 | +
|
| 136 | +VkDescriptorSetLayoutBinding sampler_c; |
| 137 | +sampler_c.binding = 6; |
| 138 | +sampler_c.descriptorCount = 2; |
| 139 | +---- |
| 140 | + |
| 141 | +If we try to update the descriptors together, the `VkWriteDescriptorSet` will look like: |
| 142 | + |
| 143 | +[source,c++] |
| 144 | +---- |
| 145 | +VkDescriptorImageInfo image_infos[5]; |
| 146 | +
|
| 147 | +VkWriteDescriptorSet writes; |
| 148 | +writes.dstBinding = 1; |
| 149 | +writes.dstArrayElement = 0; |
| 150 | +writes.descriptorCount = 5; |
| 151 | +writes.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; |
| 152 | +writes.pImageInfo = image_infos; |
| 153 | +---- |
| 154 | + |
| 155 | +Here the `VkWriteDescriptorSet::descriptorCount` is `5`. It will set the following: |
| 156 | + |
| 157 | +- `image_infos[0]` to binding 1, index 0 |
| 158 | +- `image_infos[1]` to binding 1, index 1 |
| 159 | +- `image_infos[2]` to binding 2, index 0 |
| 160 | +- `image_infos[3]` to binding 6, index 0 |
| 161 | +- `image_infos[4]` to binding 6, index 1 |
0 commit comments