VK_KHR_vertex_attribute_divisor
Promoted from VK_EXT_vertex_attribute_divisor, this extension allows
instance-rate vertex attributes to be repeated for certain number of instances
instead of advancing for every instance when instanced rendering is enabled.
1. Problem Statement
In other APIs such as OpenGL, it is possible to use the same values of vertex
attributes for a number of successive instances when instanced rendering is
enabled.
This is commonly referred to as "vertex attribute divisor".
For example, if the divisor is N, the same vertex attribute will be applied
to N successive instances before moving on to the next vertex attribute.
A value of 0 allows the same vertex attribute to be applied to all instances.
This functionality was originally introduced in Vulkan with the
VK_EXT_vertex_attribute_divisor extension.
2. Proposal
The API in VK_EXT_vertex_attribute_divisor is promoted to KHR with the
following exception:
The VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR struct contains
an additional property supportsNonZeroFirstInstance, compared to
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT.
The vertex attribute divisor can be specified with:
typedef struct VkVertexInputBindingDivisorDescriptionKHR {
uint32_t binding;
uint32_t divisor;
} VkVertexInputBindingDivisorDescriptionKHR;
which specifies a divisor value for the given vertex binding.
divisor is the number of successive instances that will use the same value of
the vertex attribute when instanced rendering is enabled.
For example, if the divisor is N, the same vertex attribute will be applied
to N successive instances before moving on to the next vertex attribute.
The above is specified once per vertex binding in:
typedef struct VkPipelineVertexInputDivisorStateCreateInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t vertexBindingDivisorCount;
const VkVertexInputBindingDivisorDescriptionKHR* pVertexBindingDivisors;
} VkPipelineVertexInputDivisorStateCreateInfoKHR;
The maximum allowed divisor value can be queried with the following struct when
chained to VkPhysicalDeviceProperties2:
typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR {
VkStructureType sType;
void* pNext;
uint32_t maxVertexAttribDivisor;
VkBool32 supportsNonZeroFirstInstance;
} VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR;
In the above, supportsNonZeroFirstInstance specifies whether a non-zero value
for the firstInstance parameter of drawing commands is supported when
VkVertexInputBindingDivisorDescriptionKHR::divisor (or the equivalent
dynamically set state) is not 1. Note that this property is new compared to
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT.
The VK_EXT_vertex_input_dynamic_state and VK_EXT_shader_object extensions
provide the vkCmdSetVertexInputEXT function, allowing the vertex attribute
divisor state to be dynamically set.
The functionality of this extension is controlled by the following features:
typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR {
VkStructureType sType;
void* pNext;
VkBool32 vertexAttributeInstanceRateDivisor;
VkBool32 vertexAttributeInstanceRateZeroDivisor;
} VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR;
-
vertexAttributeInstanceRateDivisorspecifies whether the functionality in the extension is supported. -
vertexAttributeInstanceRateZeroDivisorspecifies whether a zero value forVkVertexInputBindingDivisorDescriptionKHR::divisoris supported.
3. Examples
The vertex attribute divisor can be specified when creating a graphics pipeline as such:
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,
...
};