Pipeline Dynamic State
Overview
When creating a graphics VkPipeline
object the logical flow for setting state is:
// Using viewport state as an example
VkViewport viewport = {0.0, 0.0, 32.0, 32.0, 0.0, 1.0};
// Set value of state
VkPipelineViewportStateCreateInfo viewportStateCreateInfo;
viewportStateCreateInfo.pViewports = &viewport;
viewportStateCreateInfo.viewportCount = 1;
// Create the pipeline with the state value set
VkGraphicsPipelineCreateInfo pipelineCreateInfo;
pipelineCreateInfo.pViewportState = &viewportStateCreateInfo;
vkCreateGraphicsPipelines(pipelineCreateInfo, &pipeline);
vkBeginCommandBuffer();
// Select the pipeline and draw with the state's static value
vkCmdBindPipeline(pipeline);
vkCmdDraw();
vkEndCommandBuffer();
When the VkPipeline
uses dynamic state, some pipeline information can be omitted at creation time and instead set during recording of the command buffer. The new logical flow is:
// Using viewport state as an example
VkViewport viewport = {0.0, 0.0, 32.0, 32.0, 0.0, 1.0};
VkDynamicState dynamicState = VK_DYNAMIC_STATE_VIEWPORT;
// not used now
VkPipelineViewportStateCreateInfo viewportStateCreateInfo;
viewportStateCreateInfo.pViewports = nullptr;
// still need to say how many viewports will be used here
viewportStateCreateInfo.viewportCount = 1;
// Set the state as being dynamic
VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo;
dynamicStateCreateInfo.dynamicStateCount = 1;
dynamicStateCreateInfo.pDynamicStates = &dynamicState;
// Create the pipeline with state value not known
VkGraphicsPipelineCreateInfo pipelineCreateInfo;
pipelineCreateInfo.pViewportState = &viewportStateCreateInfo;
pipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
vkCreateGraphicsPipelines(pipelineCreateInfo, &pipeline);
vkBeginCommandBuffer();
vkCmdBindPipeline(pipeline);
// Set the state for the pipeline at recording time
vkCmdSetViewport(viewport);
vkCmdDraw();
viewport.height = 64.0;
// set a new state value between draws
vkCmdSetViewport(viewport);
vkCmdDraw();
vkEndCommandBuffer();
When to use dynamic state
Vulkan is a tool, so as with most things, and there is no single answer for this. |
Some implementations might have a performance loss using some certain VkDynamicState
state over a static value, but dynamic states might prevent an application from having to create many permutations of pipeline objects which might be a bigger desire for the application.
Dynamic state lifetime
The spec talks about how there is a dynamic state lifetime. The following best describes it in some examples:
// example 1 - valid
vkCmdSetViewport()
vkCmdBindPipeline() // static state
vkCmdDraw()
// example 2 - valid
vkCmdBindPipeline() // static state
vkCmdSetViewport()
vkCmdBindPipeline() // dynamic state
vkCmdDraw()
// example 3 - invalid (VUID-vkCmdDraw-None-07831)
vkCmdBindPipeline() // static state
vkCmdBindPipeline() // dynamic state
vkCmdDraw()
// example 4 - invalid (VUID-vkCmdDraw-None-08608)
vkCmdBindPipeline() // dynamic state
vkCmdBindPipeline() // static state
vkCmdSetViewport()
vkCmdDraw()
// example 5 - invalid (VUID-vkCmdDraw-None-07831)
vkCmdSetViewport()
vkCmdBindPipeline() // static state
vkCmdBindPipeline() // dynamic state
vkCmdDraw()
// example 6 - invalid (VUID-vkCmdDraw-None-07831)
vkCmdSetViewport()
vkCmdBindPipeline() // static state
vkCmdDraw()
vkCmdBindPipeline() // dynamic state
vkCmdDraw()
What states are dynamic
The full list of possible dynamic states can be found in VkDynamicState.
The VK_EXT_extended_dynamic_state
, VK_EXT_extended_dynamic_state2
, VK_EXT_extended_dynamic_state3
, VK_EXT_vertex_input_dynamic_state
, VK_EXT_attachment_feedback_loop_dynamic_state
and VK_EXT_color_write_enable
extensions were added with the goal to support applications that need to reduce the number of pipeline state objects they compile and bind.