Skip to content

Commit f713e9c

Browse files
committed
addressing more comments.
1 parent dd51a38 commit f713e9c

File tree

1 file changed

+75
-5
lines changed

1 file changed

+75
-5
lines changed

en/Building_a_Simple_Engine/Tooling/05_extensions.adoc

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ While VK_EXT_robustness2 is the focus of this section, there are other extension
139139

140140
==== VK_KHR_buffer_device_address
141141

142-
This extension allows you to use physical device addresses for buffers, which can be useful for advanced techniques. It includes robustness features for handling invalid addresses:
142+
This extension allows you to use physical device addresses for buffers, which can be useful for advanced techniques. It includes robustness features for handling invalid addresses (when combined with robust access features like VK_EXT_robustness2 or core robustBufferAccess):
143143

144144
[source,cpp]
145145
----
@@ -148,19 +148,28 @@ void enable_buffer_device_address(vk::DeviceCreateInfo& device_create_info,
148148
enabled_extensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
149149
device_create_info.setPEnabledExtensionNames(enabled_extensions);
150150
151+
// Enable Buffer Device Address features
151152
vk::PhysicalDeviceBufferDeviceAddressFeatures buffer_device_address_features{};
152153
buffer_device_address_features.setBufferDeviceAddress(VK_TRUE);
153154
buffer_device_address_features.setBufferDeviceAddressCaptureReplay(VK_TRUE);
154155
155-
// Add to the pNext chain
156+
// Optionally chain robustness features to ensure invalid addresses read as zero and writes are discarded
157+
// (If you've already enabled VK_EXT_robustness2 elsewhere, this is not required here.)
158+
vk::PhysicalDeviceRobustness2FeaturesEXT robustness2_features{};
159+
robustness2_features.setRobustBufferAccess2(VK_TRUE);
160+
robustness2_features.setRobustImageAccess2(VK_TRUE);
161+
robustness2_features.setNullDescriptor(VK_TRUE);
162+
163+
// Chain features: robustness2 -> BDA -> existing pNext
164+
robustness2_features.pNext = &buffer_device_address_features;
156165
buffer_device_address_features.pNext = device_create_info.pNext;
157-
device_create_info.pNext = &buffer_device_address_features;
166+
device_create_info.pNext = &robustness2_features;
158167
}
159168
----
160169

161170
==== VK_EXT_descriptor_indexing
162171

163-
This extension allows for more flexible descriptor indexing, including robustness features for handling out-of-bounds descriptor array accesses:
172+
This extension allows for more flexible descriptor indexing, including robustness-related capabilities such as tolerating out-of-bounds indices (reads become zero when robust access is enabled), partially bound descriptor sets, and update-after-bind. To actually make use of these behaviors you need to enable both device features and descriptor set layout binding flags:
164173

165174
[source,cpp]
166175
----
@@ -170,17 +179,78 @@ void enable_descriptor_indexing(vk::DeviceCreateInfo& device_create_info,
170179
device_create_info.setPEnabledExtensionNames(enabled_extensions);
171180
172181
vk::PhysicalDeviceDescriptorIndexingFeatures indexing_features{};
182+
// Shader indexing capabilities (commonly needed alongside robustness)
183+
indexing_features.setShaderSampledImageArrayNonUniformIndexing(VK_TRUE);
184+
indexing_features.setShaderStorageBufferArrayNonUniformIndexing(VK_TRUE);
185+
186+
// Robustness-enabling behaviors
173187
indexing_features.setRuntimeDescriptorArray(VK_TRUE);
174188
indexing_features.setDescriptorBindingPartiallyBound(VK_TRUE);
175189
indexing_features.setDescriptorBindingSampledImageUpdateAfterBind(VK_TRUE);
176190
indexing_features.setDescriptorBindingStorageBufferUpdateAfterBind(VK_TRUE);
191+
indexing_features.setDescriptorBindingUpdateUnusedWhilePending(VK_TRUE);
177192
178-
// Add to the pNext chain
193+
// Add to the pNext chain (can be chained together with VK_EXT_robustness2)
179194
indexing_features.pNext = device_create_info.pNext;
180195
device_create_info.pNext = &indexing_features;
181196
}
182197
----
183198

199+
For descriptor arrays, you must also specify binding flags at layout creation time:
200+
201+
[source,cpp]
202+
----
203+
// Example: descriptor set layout with a runtime-sized array that can be partially bound
204+
vk::DescriptorSetLayoutBinding binding{};
205+
binding.binding = 0;
206+
binding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
207+
binding.descriptorCount = 128; // example array size; for true runtime arrays also enable variable descriptor counts
208+
binding.stageFlags = vk::ShaderStageFlagBits::eFragment;
209+
210+
vk::DescriptorBindingFlags binding_flags =
211+
vk::DescriptorBindingFlagBits::ePartiallyBound |
212+
vk::DescriptorBindingFlagBits::eUpdateAfterBind;
213+
214+
vk::DescriptorSetLayoutBindingFlagsCreateInfo flags_ci{};
215+
flags_ci.setBindingCount(1);
216+
flags_ci.setPBindingFlags(&binding_flags);
217+
218+
vk::DescriptorSetLayoutCreateInfo dsl_ci{};
219+
dsl_ci.setPBindings(&binding);
220+
dsl_ci.setBindingCount(1);
221+
// Required when using update-after-bind flags
222+
// (some descriptor types require pool and layout flags to match update-after-bind usage)
223+
dsl_ci.flags |= vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool;
224+
225+
dsl_ci.pNext = &flags_ci;
226+
227+
vk::raii::DescriptorSetLayout set_layout{device, dsl_ci};
228+
----
229+
230+
If you need truly variable-length descriptor arrays at runtime, also enable variable descriptor counts and use the corresponding allocate info:
231+
232+
[source,cpp]
233+
----
234+
// Enable the device feature
235+
// indexing_features.setDescriptorBindingVariableDescriptorCount(VK_TRUE); // do this where features are enabled
236+
237+
uint32_t max_descriptors_for_set0 = 1024; // requested at allocation time
238+
239+
vk::DescriptorSetVariableDescriptorCountAllocateInfo variable_counts_info{};
240+
variable_counts_info.setDescriptorSetCount(1);
241+
variable_counts_info.setPDescriptorCounts(&max_descriptors_for_set0);
242+
243+
vk::DescriptorSetAllocateInfo alloc_info{};
244+
alloc_info.setDescriptorPool(descriptor_pool);
245+
alloc_info.setDescriptorSetCount(1);
246+
alloc_info.setPSetLayouts(&*set_layout);
247+
alloc_info.pNext = &variable_counts_info;
248+
249+
auto descriptor_sets = vk::raii::DescriptorSets{device, alloc_info};
250+
----
251+
252+
Note: With VK_EXT_robustness2's nullDescriptor = VK_TRUE and descriptor indexing's partially-bound behavior, unbound array elements will read as zero rather than invoking undefined behavior.
253+
184254
=== Combining Robustness Extensions with Debugging Tools
185255

186256
For maximum effectiveness, combine robustness extensions with the debugging tools we discussed in previous sections:

0 commit comments

Comments
 (0)