VK_EXT_descriptor_indexing
在 Vulkan 1.2 中提升为核心 |
此扩展旨在分解为几个不同的、较小的功能,以便实现可以在可能的情况下添加对每个功能的支持。
绑定后更新
如果没有此扩展,则不允许应用程序中的描述符在记录命令缓冲区和执行命令缓冲区之间进行更新。 使用此扩展,应用程序可以查询所使用描述符类型的 descriptorBinding*UpdateAfterBind
支持,这允许应用程序在记录和执行之间进行更新。
示例
如果应用程序具有 |
在启用对绑定后更新的所需功能支持后,应用程序需要设置以下内容才能使用可以在绑定后更新的描述符
-
从其中分配描述符的任何
VkDescriptorPool
的VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT
标志。 -
来自该描述符的任何
VkDescriptorSetLayout
的VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT
标志。 -
描述符将使用的
VkDescriptorSetLayout
中每个绑定的VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT
。
以下代码示例说明了启用绑定后更新和不启用之间的区别

部分绑定
使用 descriptorBindingPartiallyBound
功能并在 VkDescriptorSetLayoutBindingFlagsCreateInfo::pBindingFlags
中使用 VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT
,应用程序开发人员不需要在使用时更新所有描述符。
例如,如果应用程序的 GLSL 具有
layout(set = 0, binding = 0) uniform sampler2D textureSampler[64];
但仅绑定数组中的前 32 个插槽。 这也依赖于应用程序知道它不会索引到数组中未绑定的插槽。
动态索引
通常,当应用程序索引到绑定描述符数组中时,索引需要在编译时已知。 使用 shader*ArrayDynamicIndexing
功能,可以通过“动态统一”整数索引某种类型的描述符。 这已经作为大多数描述符的 VkPhysicalDeviceFeatures
支持,但此扩展添加了 VkPhysicalDeviceDescriptorIndexingFeatures
结构,使实现可以公开对输入附件、统一纹理缓冲区和存储纹理缓冲区的动态统一索引的支持。
这里的关键词是“统一”,这意味着 SPIR-V 调用组中的所有调用都需要使用相同的动态索引。 这转换为 vkCmdDraw*
调用中的所有调用或 vkCmdDispatch*
调用的单个工作组。
GLSL 中动态统一索引的示例
layout(set = 0, binding = 0) uniform sampler2D mySampler[64];
layout(set = 0, binding = 1) uniform UniformBufferObject {
int textureId;
} ubo;
// ...
void main() {
// ...
vec4 samplerColor = texture(mySampler[ubo.textureId], uvCoords);
// ...
}
此示例是“动态的”,因为它在运行时才知道 ubo.textureId
的值。 这也是“统一的”,因为所有调用都将在此着色器中使用 ubo.textureId
。
动态非统一索引
动态 非统一 意味着调用可能会以不同的方式索引到描述符数组中,但在运行时才会知道。 此扩展在 VkPhysicalDeviceDescriptorIndexingFeatures
中公开了一组 shader*ArrayNonUniformIndexing
功能位,以显示实现支持哪些描述符类型的动态非统一索引。 SPIR-V 扩展添加了一个 NonUniform
修饰符,可以使用添加的 nonuniformEXT
关键字在 GLSL 中设置该修饰符。
GLSL 中动态非统一索引的示例
#version450
#extension GL_EXT_nonuniform_qualifier : enable
layout(set = 0, binding = 0) uniform sampler2D mySampler[64];
layout(set = 0, binding = 1) uniform UniformBufferObject {
int textureId;
} ubo;
// ...
void main() {
// ...
if (uvCoords.x > runtimeThreshold) {
index = 0;
} else {
index = 1;
}
vec4 samplerColor = texture(mySampler[nonuniformEXT(index)], uvCoords);
// ...
}
此示例是非统一的,因为一些调用索引 mySampler[0]
,而另一些调用索引 mySampler[1]
。 在这种情况下需要 nonuniformEXT()
。