VK_KHR_vertex_attribute_divisor
此扩展从 VK_EXT_vertex_attribute_divisor
提升而来,允许在启用实例渲染时,实例速率顶点属性对于一定数量的实例重复使用,而不是每个实例都前进。
1. 问题陈述
在其他 API(如 OpenGL)中,可以在启用实例渲染时,将相同的顶点属性值用于多个连续的实例。这通常被称为“顶点属性除数”。例如,如果除数为 N
,则相同的顶点属性将应用于 N
个连续的实例,然后再移动到下一个顶点属性。值为 0
允许将相同的顶点属性应用于所有实例。
此功能最初在 Vulkan 中通过 VK_EXT_vertex_attribute_divisor
扩展引入。
2. 提案
VK_EXT_vertex_attribute_divisor
中的 API 提升为 KHR,但以下情况除外:
与 VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT
相比,VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR
结构包含一个额外的属性 supportsNonZeroFirstInstance
。
顶点属性除数可以使用以下方式指定:
typedef struct VkVertexInputBindingDivisorDescriptionKHR {
uint32_t binding;
uint32_t divisor;
} VkVertexInputBindingDivisorDescriptionKHR;
该方式指定给定顶点绑定的除数值。当启用实例渲染时,divisor
是将使用相同顶点属性值的连续实例的数量。例如,如果除数为 N
,则相同的顶点属性将应用于 N
个连续的实例,然后再移动到下一个顶点属性。
以上内容在以下位置为每个顶点绑定指定一次:
typedef struct VkPipelineVertexInputDivisorStateCreateInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t vertexBindingDivisorCount;
const VkVertexInputBindingDivisorDescriptionKHR* pVertexBindingDivisors;
} VkPipelineVertexInputDivisorStateCreateInfoKHR;
当链接到 VkPhysicalDeviceProperties2
时,可以使用以下结构查询允许的最大除数值:
typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR {
VkStructureType sType;
void* pNext;
uint32_t maxVertexAttribDivisor;
VkBool32 supportsNonZeroFirstInstance;
} VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR;
在上述内容中,supportsNonZeroFirstInstance
指定当 VkVertexInputBindingDivisorDescriptionKHR::divisor
(或等效的动态设置状态)不为 1
时,是否支持绘制命令的 firstInstance
参数的非零值。请注意,与 VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT
相比,此属性是新增的。
VK_EXT_vertex_input_dynamic_state
和 VK_EXT_shader_object
扩展提供了 vkCmdSetVertexInputEXT
函数,允许动态设置顶点属性除数状态。
此扩展的功能由以下特性控制:
typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR {
VkStructureType sType;
void* pNext;
VkBool32 vertexAttributeInstanceRateDivisor;
VkBool32 vertexAttributeInstanceRateZeroDivisor;
} VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR;
-
vertexAttributeInstanceRateDivisor
指定是否支持扩展中的功能。 -
vertexAttributeInstanceRateZeroDivisor
指定是否支持VkVertexInputBindingDivisorDescriptionKHR::divisor
的零值。
3. 示例
可以在创建图形管线时指定顶点属性除数,如下所示:
const VkVertexInputBindingDivisorDescriptionKHR divisorDesc =
{
.binding = 0,
.divisor = 4,
};
const VkPipelineVertexInputDivisorStateCreateInfoKHR divisorInfo =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_KHR,
.vertexBindingDivisorCount = 1,
.pVertexBindingDivisors = &divisorDesc,
}
const VkVertexInputBindingDescription binding =
{
.binding = 0,
.stride = sizeof(Vertex),
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE,
};
const VkPipelineVertexInputStateCreateInfo viInfo =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO,
.pNext = &divisorInfo,
...
};