7.5
如之前章节所见,图形管线是大型的、复杂的,包含很多状态的对象。在很多图形应用程序中,我们期望能够高频率的改变一些状态。如果每一个状态的每一次更改都需要你创建一个新的图形管线对象,那么你的应用程序中对象的个数将会迅速的变得很大。
要精细粒度的管理状态的改变,Vulkan提供了以便定图形管线某部分为动态的能力,这意味着它们可以被命令缓冲区的命令而不是一个对象直接在运行时修改。因为这减少了Vulkan优化或者吸收状态的一部分的机会,所以,有必要显式的指定你想要变为动态的部分。这通过VkGraphicsPipelineCreateInfo类型数据的pDynamicState成员可做到,它是一个指向VkPipelineDynamicStateCreateInfo类型数据的指针,该类型定义是:
typedefstruct VkPipelineDynamicStateCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineDynamicStateCreateFlags flags;
uint32_t dynamicStateCount;
const VkDynamicState* pDynamicStates;
} VkPipelineDynamicStateCreateInfo;
VkPipelineDynamicStateCreateInfo的sType应置为VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,pNext应置为nullptr。Flags域被保留,应置为0。
你希望变为动态的状态的个数通过dynamicStateCount指定。这是pDynamicStates所指向的数组的长度,该数组的元素是VkDynamicState枚举的值。包含了该枚举的一个成员的pDynamicStates数组告诉Vulkan你想要使用对应的动态状态设置命令。VkDynamicState的成员和含义如下:
• VK_DYNAMIC_STATE_VIEWPORT:The viewport rectangle is dynamic and will be updated
using vkCmdSetViewport().
•VK_DYNAMIC_STATE_SCISSOR: The scissor rectangle is dynamic and will be updatedusing
vkCmdSetScissor().
•VK_DYNAMIC_STATE_LINE_WIDTH: The line width is dynamic and will be updatedusing
vkCmdSetLineWidth().
•VK_DYNAMIC_STATE_DEPTH_BIAS: The depth bias parameters are dynamic and will be
updated using vkCmdSetDepthBias().
•VK_DYNAMIC_STATE_BLEND_CONSTANTS: The color blend constants are dynamic and
will be updated using vkCmdSetBlendConstants().
•VK_DYNAMIC_STATE_DEPTH_BOUNDS: The depth bounds parameters are dynamic and will
be updated using vkCmdSetDepthBounds().
•VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, and
VK_DYNAMIC_STATE_STENCIL_REFERENCE: The corresponding stencilparameters are
dynamic and will be updated using vkCmdSetStencilCompareMask(),
vkCmdSetStencilWriteMask(), and vkCmdSetStencilReference(),
respectively
如果一个状态被指定为动态的,那么在绑定管线是你需要负责设置这个状态。如果状态没有被标志为动态,那么就被认为是静态的,在绑定管线是被设置。绑定管线到静态状态会导致动态状态未定义。原因是如果静态状态没有被使用或者被认定为有效时,Vulkan实现也许优化静态状态进入管线对象内部,且不会真正把他们编程到硬件。当一个带有标记为动态的管线被随即绑定,动态状态在硬件中是否一致是未定义的。
然而,当你在标记为相同的动态状态的不同管线中切换时,状态仍跨越不同的绑定保持一致。Table7.1展示如下:
Table 7.1: Dynamic and Static StateValidity
如你在Table 7.1中所见,状态变得未定义的唯一一种情形发生在你在管线里从标记为静态状态切换到状态标记为动态时。在其他所有情形下,状态都是良好的被定义,状态来自于通过管线的状态或者使用合适的命令设置的动态状态。
如果你设置一个当前绑定为静态状态的管线为动态状态,且然后用这个管线绘制,那么会造成未知的结果。这个效果也许是忽略状态设置命令,继续使用静态状态版本的管线,或者是突出状态设置命令并使用新的管线状态,又或者是损坏状态并导致程序崩溃。这个效果在不同的Vulkan实现之间是不同的,取决于哪个被错误的覆盖的状态。
设置动态状态,然后和一个管线绑定,将导致动态状态被使用。然而,最好是先绑定管线,然后在绑定任何状态来避免潜在的为定义行为发生。
总结
本章提供了对Vulkan图形管线快速的讲解。管线由多个阶段组成,一些阶段可以被配置,其中一些是固定功能但可以配置,和一些由外部提供的功能强大的着色器程序。在第六章“着色器和管线”给出的管线对象的基础概念之上,这里介绍了图形管线对象。这个对象包括大量的固定功能状态。尽管本章内示例构造的管线相当简单,为后面的章节将会讲到的更加复杂和强表述能力的管线打下了基础。