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;
-
vertexAttributeInstanceRateDivisor
specifies whether the functionality in the extension is supported. -
vertexAttributeInstanceRateZeroDivisor
specifies whether a zero value forVkVertexInputBindingDivisorDescriptionKHR::divisor
is 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,
...
};