命令缓冲区
命令缓冲区是用于记录命令的对象,这些命令可以随后提交到设备队列以供执行。命令缓冲区分为两个级别 - 主命令缓冲区,它可以执行辅助命令缓冲区,并提交到队列;以及辅助命令缓冲区,它可以由主命令缓冲区执行,并且不直接提交到队列。
命令缓冲区由 VkCommandBuffer
句柄表示
// Provided by VK_VERSION_1_0
VK_DEFINE_HANDLE(VkCommandBuffer)
记录的命令包括将管线和描述符集绑定到命令缓冲区的命令、修改动态状态的命令、绘制命令(用于图形渲染)、分发命令(用于计算)、执行辅助命令缓冲区的命令(仅适用于主命令缓冲区)、复制缓冲区和图像的命令以及其他命令。
每个命令缓冲区独立于其他命令缓冲区管理状态。主命令缓冲区和辅助命令缓冲区之间,或辅助命令缓冲区之间不存在状态继承。当命令缓冲区开始记录时,该命令缓冲区中的所有状态都为未定义。当记录在主命令缓冲区上执行辅助命令缓冲区时,辅助命令缓冲区不会从主命令缓冲区继承任何状态,并且在记录执行辅助命令缓冲区的命令后,主命令缓冲区的所有状态都为未定义。此规则有一个例外 - 如果主命令缓冲区位于渲染通道实例内,则渲染通道和子通道状态不会因执行辅助命令缓冲区而受到干扰。对于依赖于状态的命令(例如绘制和分发),这些命令所消耗的任何状态必须不是未定义的。
VkCommandBufferInheritanceViewportScissorInfoNV 定义了一个例外,允许有限地继承动态视口和裁剪状态。
命令缓冲区生命周期
每个命令缓冲区始终处于以下状态之一
- 初始
-
当分配命令缓冲区时,它处于初始状态。一些命令能够将命令缓冲区(或一组命令缓冲区)从任何可执行、记录或无效状态重置回此状态。处于初始状态的命令缓冲区只能移动到记录状态或释放。
- 记录
-
vkBeginCommandBuffer 将命令缓冲区的状态从初始状态更改为记录状态。一旦命令缓冲区处于记录状态,就可以使用
vkCmd*
命令记录到命令缓冲区。 - 可执行
-
vkEndCommandBuffer 结束命令缓冲区的记录,并将其从记录状态移动到可执行状态。可执行的命令缓冲区可以提交、重置或记录到另一个命令缓冲区。
- 待处理
-
命令缓冲区的队列提交将命令缓冲区的状态从可执行状态更改为待处理状态。在待处理状态期间,应用程序必须不要尝试以任何方式修改命令缓冲区 - 因为设备可能正在处理记录到其中的命令。一旦命令缓冲区的执行完成,命令缓冲区要么恢复为可执行状态,要么如果使用
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
记录,则移动到无效状态。应使用同步命令来检测何时发生这种情况。 - 无效
-
某些操作,例如修改或删除命令缓冲区中使用的资源,会将该命令缓冲区的状态转换为无效状态。处于无效状态的命令缓冲区只能被重置或释放。
任何操作命令缓冲区的命令都有其自身对命令缓冲区状态的要求,这些要求在命令的有效使用约束中详细说明。
重置命令缓冲区是一种丢弃任何先前记录的命令并将命令缓冲区置于初始状态的操作。重置操作通过vkResetCommandBuffer 或 vkResetCommandPool,或者作为 vkBeginCommandBuffer 的一部分(它还会将命令缓冲区置于记录状态)发生。
二级命令缓冲区可以通过 vkCmdExecuteCommands 记录到主命令缓冲区中。这在一定程度上将两个命令缓冲区的生命周期联系在一起 - 如果主命令缓冲区被提交到队列,则主命令缓冲区和记录到其中的任何二级命令缓冲区都会移动到待处理状态。一旦主命令缓冲区执行完成,它也会对其中记录的任何二级命令缓冲区执行完成。在每个命令缓冲区的所有执行完成后,它们各自移动到其相应的完成状态(如上所述,移动到可执行状态或无效状态)。
如果二级命令缓冲区移动到无效状态或初始状态,则记录它的所有主命令缓冲区都将移动到无效状态。主命令缓冲区移动到任何其他状态不会影响其中记录的二级命令缓冲区的状态。
重置或释放主命令缓冲区会删除与记录到其中的所有二级命令缓冲区的生命周期联系。 |
命令池
命令池是从中分配命令缓冲区内存的不透明对象,它允许实现跨多个命令缓冲区分摊资源创建的成本。命令池是外部同步的,这意味着命令池不得在多个线程中并发使用。这包括通过在从该池分配的任何命令缓冲区上记录命令以及分配、释放和重置命令缓冲区或池本身的操作来使用。
命令池由 VkCommandPool
句柄表示
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool)
要创建命令池,请调用
// Provided by VK_VERSION_1_0
VkResult vkCreateCommandPool(
VkDevice device,
const VkCommandPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkCommandPool* pCommandPool);
-
device
是创建命令池的逻辑设备。 -
pCreateInfo
是指向 VkCommandPoolCreateInfo 结构的指针,该结构指定命令池对象的状态。 -
pAllocator
控制主机内存分配,如内存分配章节中所述。 -
pCommandPool
是指向 VkCommandPool 句柄的指针,创建的池将在其中返回。
VkCommandPoolCreateInfo
结构定义为
// Provided by VK_VERSION_1_0
typedef struct VkCommandPoolCreateInfo {
VkStructureType sType;
const void* pNext;
VkCommandPoolCreateFlags flags;
uint32_t queueFamilyIndex;
} VkCommandPoolCreateInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是 VkCommandPoolCreateFlagBits 的位掩码,指示池和从中分配的命令缓冲区的使用行为。 -
queueFamilyIndex
指定一个队列族,如 队列族属性部分所述。从此命令池分配的所有命令缓冲区必须在来自同一队列族的队列上提交。
可以在 VkCommandPoolCreateInfo::flags
中设置的位,指定命令池的使用行为,包括
// Provided by VK_VERSION_1_0
typedef enum VkCommandPoolCreateFlagBits {
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
// Provided by VK_VERSION_1_1
VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004,
} VkCommandPoolCreateFlagBits;
-
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT
指定从池分配的命令缓冲区将是短期的,这意味着它们将在相对较短的时间内重置或释放。实现可以使用此标志来控制池内的内存分配行为。 -
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
允许从池中分配的任何命令缓冲区单独重置为初始状态;可以通过调用vkResetCommandBuffer,或者在调用vkBeginCommandBuffer时隐式重置。如果池中未设置此标志,则 必须 不能为从该池分配的任何命令缓冲区调用vkResetCommandBuffer
。 -
VK_COMMAND_POOL_CREATE_PROTECTED_BIT
指定从池中分配的命令缓冲区是受保护的命令缓冲区。
// Provided by VK_VERSION_1_0
typedef VkFlags VkCommandPoolCreateFlags;
VkCommandPoolCreateFlags
是一个位掩码类型,用于设置零个或多个 VkCommandPoolCreateFlagBits 的掩码。
要修剪命令池,请调用
// Provided by VK_VERSION_1_1
void vkTrimCommandPool(
VkDevice device,
VkCommandPool commandPool,
VkCommandPoolTrimFlags flags);
或者等效的命令
// Provided by VK_KHR_maintenance1
void vkTrimCommandPoolKHR(
VkDevice device,
VkCommandPool commandPool,
VkCommandPoolTrimFlags flags);
-
device
是拥有命令池的逻辑设备。 -
commandPool
是要修剪的命令池。 -
flags
保留供将来使用。
修剪命令池会将命令池中未使用的内存回收给系统。从池中分配的命令缓冲区不受此命令的影响。
此命令为应用程序提供了一些对命令池使用的内部内存分配的控制。 未使用的内存通常来自已记录然后重置的命令缓冲区,因此它们不再使用内存。重置时,命令缓冲区可以将内存返回给其命令池,但是将内存从命令池释放到系统的唯一方法是调用 vkResetCommandPool,而当该池中的任何命令缓冲区仍在使用时,无法执行此操作。后续的命令缓冲区记录操作将重用此内存,但是由于总的内存需求会随着时间波动,因此未使用的内存会累积。 在这种情况下,修剪命令池 可能 有助于将未使用的内存返回给系统,从而将池分配的总的未完成内存返回到更“平均”的值。 实现使用许多内部分配策略,这使得无法保证所有未使用的内存都释放回系统。例如,命令池的实现 可能 涉及从系统批量分配内存并从该内存中进行子分配。在这样的实现中,任何持有对批量分配的引用的活动命令缓冲区都将阻止释放该分配,即使仅使用批量分配的一小部分也是如此。 在大多数情况下,修剪将导致减少已分配但未使用的内存,但是不能保证“理想”的行为。 修剪 可能 是一项昂贵的操作,并且 不应该 频繁调用。修剪 应该 被视为在应用程序已知存在足够未使用的内存(足以使修剪的成本“值得”)的情况下缓解内存压力的一种方式。 |
// Provided by VK_VERSION_1_1
typedef VkFlags VkCommandPoolTrimFlags;
或等效的
// Provided by VK_KHR_maintenance1
typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR;
VkCommandPoolTrimFlags
是一个用于设置掩码的位掩码类型,但目前保留供将来使用。
要重置命令池,请调用
// Provided by VK_VERSION_1_0
VkResult vkResetCommandPool(
VkDevice device,
VkCommandPool commandPool,
VkCommandPoolResetFlags flags);
-
device
是拥有命令池的逻辑设备。 -
commandPool
是要重置的命令池。 -
flags
是 VkCommandPoolResetFlagBits 的位掩码,用于控制重置操作。
重置命令池会将从命令池分配的所有命令缓冲区的所有资源回收回命令池。从命令池分配的所有命令缓冲区都将置于初始状态。
从另一个 VkCommandPool 分配的任何处于记录或可执行状态的主命令缓冲区,并且其中记录了从 commandPool
分配的辅助命令缓冲区,都将变为无效。
在 vkResetCommandPool::flags
中 可以 设置的位,控制重置操作,包括
// Provided by VK_VERSION_1_0
typedef enum VkCommandPoolResetFlagBits {
VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
} VkCommandPoolResetFlagBits;
-
VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT
指定重置命令池会将命令池中的所有资源回收回系统。
// Provided by VK_VERSION_1_0
typedef VkFlags VkCommandPoolResetFlags;
VkCommandPoolResetFlags
是一个位掩码类型,用于设置零个或多个 VkCommandPoolResetFlagBits 的掩码。
要销毁命令池,请调用
// Provided by VK_VERSION_1_0
void vkDestroyCommandPool(
VkDevice device,
VkCommandPool commandPool,
const VkAllocationCallbacks* pAllocator);
-
device
是销毁命令池的逻辑设备。 -
commandPool
是要销毁的命令池的句柄。 -
pAllocator
控制主机内存分配,如内存分配章节中所述。
销毁池时,将 释放 从该池分配的所有命令缓冲区。
从另一个 VkCommandPool 分配的任何处于记录或可执行状态的主命令缓冲区,并且其中记录了从 commandPool
分配的辅助命令缓冲区,都将变为无效。
命令缓冲区分配和管理
要分配命令缓冲区,请调用
// Provided by VK_VERSION_1_0
VkResult vkAllocateCommandBuffers(
VkDevice device,
const VkCommandBufferAllocateInfo* pAllocateInfo,
VkCommandBuffer* pCommandBuffers);
-
device
是拥有命令池的逻辑设备。 -
pAllocateInfo
是指向 VkCommandBufferAllocateInfo 结构的指针,该结构描述了分配的参数。 -
pCommandBuffers
是一个指向 VkCommandBuffer 句柄数组的指针,其中返回生成的命令缓冲区对象。该数组的长度必须至少为pAllocateInfo
的commandBufferCount
成员指定的值。每个分配的命令缓冲区都处于初始状态。
vkAllocateCommandBuffers
可以用于分配多个命令缓冲区。如果任何一个命令缓冲区分配失败,实现必须释放此命令中所有成功分配的命令缓冲区对象,将 pCommandBuffers
数组的所有条目设置为 NULL
,并返回错误。
在失败时用 |
当命令缓冲区首次分配时,它们处于初始状态。
VkCommandBufferAllocateInfo
结构定义如下
// Provided by VK_VERSION_1_0
typedef struct VkCommandBufferAllocateInfo {
VkStructureType sType;
const void* pNext;
VkCommandPool commandPool;
VkCommandBufferLevel level;
uint32_t commandBufferCount;
} VkCommandBufferAllocateInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
commandPool
是从中分配命令缓冲区的命令池。 -
level
是一个 VkCommandBufferLevel 值,指定命令缓冲区级别。 -
commandBufferCount
是从池中分配的命令缓冲区的数量。
指定命令缓冲区级别的 VkCommandBufferAllocateInfo::level
的可能值为
// Provided by VK_VERSION_1_0
typedef enum VkCommandBufferLevel {
VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0,
VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1,
} VkCommandBufferLevel;
-
VK_COMMAND_BUFFER_LEVEL_PRIMARY
指定主命令缓冲区。 -
VK_COMMAND_BUFFER_LEVEL_SECONDARY
指定辅助命令缓冲区。
要重置命令缓冲区,请调用
// Provided by VK_VERSION_1_0
VkResult vkResetCommandBuffer(
VkCommandBuffer commandBuffer,
VkCommandBufferResetFlags flags);
-
flags
是一个 VkCommandBufferResetFlagBits 的位掩码,控制重置操作。
可以在 vkResetCommandBuffer::flags
中设置的位,用于控制重置操作,为
// Provided by VK_VERSION_1_0
typedef enum VkCommandBufferResetFlagBits {
VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
} VkCommandBufferResetFlagBits;
-
VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT
指定命令缓冲区当前拥有的大部分或所有内存资源应该返回到父命令池。如果未设置此标志,则命令缓冲区可能保留内存资源并在记录命令时重用它们。commandBuffer
将移动到初始状态。
// Provided by VK_VERSION_1_0
typedef VkFlags VkCommandBufferResetFlags;
VkCommandBufferResetFlags
是一种位掩码类型,用于设置零个或多个 VkCommandBufferResetFlagBits 的掩码。
要释放命令缓冲区,请调用
// Provided by VK_VERSION_1_0
void vkFreeCommandBuffers(
VkDevice device,
VkCommandPool commandPool,
uint32_t commandBufferCount,
const VkCommandBuffer* pCommandBuffers);
-
device
是拥有命令池的逻辑设备。 -
commandPool
是从中分配命令缓冲区的命令池。 -
commandBufferCount
是pCommandBuffers
数组的长度。 -
pCommandBuffers
是一个指向要释放的命令缓冲区句柄数组的指针。
命令缓冲区录制
要开始录制命令缓冲区,请调用
// Provided by VK_VERSION_1_0
VkResult vkBeginCommandBuffer(
VkCommandBuffer commandBuffer,
const VkCommandBufferBeginInfo* pBeginInfo);
-
commandBuffer
是要置于录制状态的命令缓冲区的句柄。 -
pBeginInfo
是指向 VkCommandBufferBeginInfo 结构的指针,该结构定义了有关命令缓冲区如何开始录制的附加信息。
VkCommandBufferBeginInfo
结构的定义如下:
// Provided by VK_VERSION_1_0
typedef struct VkCommandBufferBeginInfo {
VkStructureType sType;
const void* pNext;
VkCommandBufferUsageFlags flags;
const VkCommandBufferInheritanceInfo* pInheritanceInfo;
} VkCommandBufferBeginInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是 VkCommandBufferUsageFlagBits 的位掩码,用于指定命令缓冲区的用法行为。 -
pInheritanceInfo
是指向 VkCommandBufferInheritanceInfo 结构的指针,如果commandBuffer
是辅助命令缓冲区,则使用该结构。如果这是主命令缓冲区,则忽略此值。
可以在 VkCommandBufferBeginInfo::flags
中设置的位,指定命令缓冲区的用法行为,如下:
// Provided by VK_VERSION_1_0
typedef enum VkCommandBufferUsageFlagBits {
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001,
VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002,
VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004,
} VkCommandBufferUsageFlagBits;
-
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
指定命令缓冲区的每次录制仅提交一次,并且每次提交之间将重置命令缓冲区并再次录制。 -
VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
指定二级命令缓冲区被认为完全位于渲染通道内部。如果这是一级命令缓冲区,则忽略此位。 -
VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT
指定命令缓冲区在处于挂起状态时可以重新提交到同一队列族的任何队列,并且可以记录到多个一级命令缓冲区中。
// Provided by VK_VERSION_1_0
typedef VkFlags VkCommandBufferUsageFlags;
VkCommandBufferUsageFlags
是一个位掩码类型,用于设置零个或多个 VkCommandBufferUsageFlagBits 的掩码。
如果命令缓冲区是二级命令缓冲区,则 VkCommandBufferInheritanceInfo
结构定义了将从一级命令缓冲区继承的任何状态。
// Provided by VK_VERSION_1_0
typedef struct VkCommandBufferInheritanceInfo {
VkStructureType sType;
const void* pNext;
VkRenderPass renderPass;
uint32_t subpass;
VkFramebuffer framebuffer;
VkBool32 occlusionQueryEnable;
VkQueryControlFlags queryFlags;
VkQueryPipelineStatisticFlags pipelineStatistics;
} VkCommandBufferInheritanceInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
renderPass
是一个 VkRenderPass 对象,定义了VkCommandBuffer
将与之兼容并且可以在其中执行的渲染通道。 -
subpass
是VkCommandBuffer
将在其中执行的渲染通道实例中的子通道索引。 -
如果
VkCommandBuffer
在渲染通道实例中执行,则framebuffer
可以引用VkCommandBuffer
将渲染到的 VkFramebuffer 对象。如果帧缓冲未知,则它可以为 VK_NULL_HANDLE。指定二级命令缓冲区执行时将使用的确切帧缓冲可能会提高命令缓冲区执行时的性能。
-
occlusionQueryEnable
指定当一级命令缓冲区中存在遮挡查询活动时,是否可以执行命令缓冲区。如果此值为VK_TRUE
,则无论一级命令缓冲区是否有遮挡查询活动,都可以执行此命令缓冲区。如果此值为VK_FALSE
,则一级命令缓冲区必须没有活动的遮挡查询。 -
queryFlags
指定在执行此二级命令缓冲区时,一级命令缓冲区中的活动遮挡查询可以使用的查询标志。如果此值包含VK_QUERY_CONTROL_PRECISE_BIT
位,则活动查询可以返回布尔结果或实际样本计数。如果未设置此位,则活动查询必须不使用VK_QUERY_CONTROL_PRECISE_BIT
位。 -
pipelineStatistics
是 VkQueryPipelineStatisticFlagBits 的位掩码,指定当执行此二级命令缓冲区时,一级命令缓冲区中的活动查询可以计数的管道统计信息的集合。如果此值包含给定位,则无论一级命令缓冲区是否有包含此位的活动管道统计信息查询,都可以执行此命令缓冲区。如果此值排除给定位,则活动管道统计信息查询必须不来自计算该统计信息的查询池。
如果 VkCommandBuffer 不会在渲染通道实例中执行,或者如果渲染通道实例是以 vkCmdBeginRendering 开始的,则 renderPass
、subpass
和 framebuffer
将被忽略。
在某些实现中,不使用 |
如果命令缓冲区处于无效或可执行状态,并且该命令缓冲区是从设置了 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
标志的命令池分配的,则 vkBeginCommandBuffer
隐式重置命令缓冲区,其行为类似于已调用 vkResetCommandBuffer
且未设置 VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT
。隐式重置后,commandBuffer
将移动到记录状态。
如果启用了 commandBufferInheritance
功能,则包括绑定的管道状态、绑定的着色器对象、绑定的顶点和索引缓冲区、绑定的描述符集和推送常量以及所有先前设置的动态状态在内的所有图形和计算状态都将由执行它的主命令缓冲区或二级命令缓冲区继承。此外,此二级命令缓冲区设置的所有状态都将继承回执行它的主命令缓冲区或二级命令缓冲区。如果未启用 commandBufferInheritance
功能,则只有少量状态会如以下指定的那样继承到二级命令缓冲区中。
如果 VkCommandBufferInheritanceInfo 的 pNext
链包含 VkCommandBufferInheritanceConditionalRenderingInfoEXT
结构体,那么该结构体控制着当主命令缓冲区中条件渲染处于激活状态时,是否可以执行命令缓冲区。
VkCommandBufferInheritanceConditionalRenderingInfoEXT
结构体定义如下:
// Provided by VK_EXT_conditional_rendering
typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT {
VkStructureType sType;
const void* pNext;
VkBool32 conditionalRenderingEnable;
} VkCommandBufferInheritanceConditionalRenderingInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
conditionalRenderingEnable
指定了当主命令缓冲区中条件渲染处于激活状态时,是否可以执行该命令缓冲区。如果该值为VK_TRUE
,那么无论主命令缓冲区是否处于激活的条件渲染状态,都可以执行此命令缓冲区。如果该值为VK_FALSE
,那么主命令缓冲区必须不能处于激活的条件渲染状态。
如果该结构体不存在,则行为等同于 conditionalRenderingEnable
为 VK_FALSE
。
要开始记录与使用 渲染通道变换在渲染通道内部执行兼容的二级命令缓冲区,请将 VkCommandBufferInheritanceRenderPassTransformInfoQCOM 添加到传递给 vkBeginCommandBuffer 命令的 VkCommandBufferInheritanceInfo 结构的 pNext
链中,指定变换光栅化的参数。
VkCommandBufferInheritanceRenderPassTransformInfoQCOM
结构体定义如下:
// Provided by VK_QCOM_render_pass_transform
typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM {
VkStructureType sType;
void* pNext;
VkSurfaceTransformFlagBitsKHR transform;
VkRect2D renderArea;
} VkCommandBufferInheritanceRenderPassTransformInfoQCOM;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
transform
是一个 VkSurfaceTransformFlagBitsKHR 值,描述要应用于渲染通道的变换。 -
renderArea
是受命令缓冲区影响的渲染区域。
当二级命令缓冲区被记录为使用 vkCmdExecuteCommands 在渲染通道实例中执行时,二级命令缓冲区的渲染通道变换参数必须与为渲染通道实例指定的渲染通道变换参数保持一致。特别是,命令缓冲区的 transform
和 renderArea
必须与渲染通道实例的 transform
和 renderArea
相同。
VkCommandBufferInheritanceViewportScissorInfoNV
结构体定义如下:
// Provided by VK_NV_inherited_viewport_scissor
typedef struct VkCommandBufferInheritanceViewportScissorInfoNV {
VkStructureType sType;
const void* pNext;
VkBool32 viewportScissor2D;
uint32_t viewportDepthCount;
const VkViewport* pViewportDepths;
} VkCommandBufferInheritanceViewportScissorInfoNV;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
viewportScissor2D
指定是否继承列出的动态状态。 -
viewportDepthCount
指定要继承的最大视口数量。当viewportScissor2D
为VK_FALSE
时,行为如同此值为零。 -
pViewportDepths
是指向 VkViewport 结构的指针,指定每个继承视口的预期深度范围。
如果 VkCommandBufferInheritanceInfo 的 pNext
链包含 VkCommandBufferInheritanceViewportScissorInfoNV
结构体,那么该结构体控制着命令缓冲区是否可以从其他命令缓冲区继承以下状态:
-
VK_DYNAMIC_STATE_SCISSOR
-
VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT
-
VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT
-
VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT
-
VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT
以及以下状态,但对继承的深度值和视口数量有限制:
-
VK_DYNAMIC_STATE_VIEWPORT
-
VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT
如果 viewportScissor2D
为 VK_FALSE
,则命令缓冲区不继承列出的动态状态,并且应该自行设置此状态。如果该结构体不存在,则行为如同 viewportScissor2D
为 VK_FALSE
。
如果 viewportScissor2D
为 VK_TRUE
,则继承列出的动态状态,并且命令缓冲区必须不设置此状态,除非通过绑定一个不将此状态指定为动态的图形管线来设置视口和剪刀计数。
由于此限制,应用程序应该确保此二级命令缓冲区中绑定的所有或不使用动态视口/剪刀计数的图形管线。 |
当命令缓冲区作为 vkCmdExecuteCommands 命令执行的一部分执行时,继承的状态(如果启用)由以下过程确定,该过程分别针对每个动态状态执行,并分别针对每个由多个值组成的动态状态的值执行(例如,多个视口)。
-
如果 i 是在 vkCmdExecuteCommands 的
pCommandBuffers
数组中执行的命令缓冲区的索引,并且如果 i > 0,并且从索引 0 到 i-1 的任何二级命令缓冲区修改了状态,则继承状态临时设置为最后一个此类二级命令缓冲区设置的最终值。静态定义状态的绑定图形管线等同于将状态设置为未定义的值。 -
否则,临时继承的状态是记录 vkCmdExecuteCommands 命令时的主命令缓冲区的状态;如果状态是未定义的,则临时继承的状态也是未定义的。
-
如果临时继承的状态是未定义的值,则不继承该状态。
-
如果临时继承的状态是一个视口,其中 n 是其视口索引,则如果 n ≥
viewportDepthCount
,或者如果 VkViewport::minDepth
或 VkViewport::maxDepth
不等于pViewportDepths
的第 nth 个元素的相应值,则不继承该状态。 -
如果临时继承的状态通过了这两个检查,则它将成为实际继承的状态。
不支持从作为不同 |
VkCommandBufferInheritanceRenderingInfo
结构体的定义如下
// Provided by VK_VERSION_1_3
typedef struct VkCommandBufferInheritanceRenderingInfo {
VkStructureType sType;
const void* pNext;
VkRenderingFlags flags;
uint32_t viewMask;
uint32_t colorAttachmentCount;
const VkFormat* pColorAttachmentFormats;
VkFormat depthAttachmentFormat;
VkFormat stencilAttachmentFormat;
VkSampleCountFlagBits rasterizationSamples;
} VkCommandBufferInheritanceRenderingInfo;
或等效的
// Provided by VK_KHR_dynamic_rendering
typedef VkCommandBufferInheritanceRenderingInfo VkCommandBufferInheritanceRenderingInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
为NULL
或指向扩展此结构的结构的指针 -
flags
是渲染通道实例使用的 VkRenderingFlagBits 的位掩码。 -
viewMask
是用于渲染的视图掩码。 -
colorAttachmentCount
是渲染通道实例中指定的颜色附件的数量。 -
pColorAttachmentFormats
是指向定义颜色附件格式的 VkFormat 值数组的指针。 -
depthAttachmentFormat
是定义深度附件格式的 VkFormat 值。 -
stencilAttachmentFormat
是定义模板附件格式的 VkFormat 值。 -
rasterizationSamples
是指定光栅化中使用的采样数的 VkSampleCountFlagBits。
如果 VkCommandBufferInheritanceInfo 的 pNext
链包含 VkCommandBufferInheritanceRenderingInfo
结构体,则该结构体控制 VkCommandBuffer 可以 在其中执行的动态渲染通道实例的参数。 如果 VkCommandBufferInheritanceInfo::renderPass
不是 VK_NULL_HANDLE,或者 VkCommandBufferBeginInfo::flags
中未指定 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
,则忽略此结构的参数。
如果 colorAttachmentCount
为 0
且启用了 variableMultisampleRate
功能,则忽略 rasterizationSamples
。
如果 depthAttachmentFormat
、stencilAttachmentFormat
或 pColorAttachmentFormats
的任何元素为 VK_FORMAT_UNDEFINED
,则表示在渲染通道中未使用相应的附件,并且会丢弃对这些附件的写入。
VkAttachmentSampleCountInfoAMD
或 VkAttachmentSampleCountInfoNV
结构定义如下:
// Provided by VK_AMD_mixed_attachment_samples with VK_VERSION_1_3 or VK_KHR_dynamic_rendering
typedef struct VkAttachmentSampleCountInfoAMD {
VkStructureType sType;
const void* pNext;
uint32_t colorAttachmentCount;
const VkSampleCountFlagBits* pColorAttachmentSamples;
VkSampleCountFlagBits depthStencilAttachmentSamples;
} VkAttachmentSampleCountInfoAMD;
或等效的
// Provided by VK_NV_framebuffer_mixed_samples with VK_VERSION_1_3 or VK_KHR_dynamic_rendering
typedef VkAttachmentSampleCountInfoAMD VkAttachmentSampleCountInfoNV;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
为NULL
或指向扩展此结构的结构的指针 -
colorAttachmentCount
是渲染通道实例中指定的颜色附件的数量。 -
pColorAttachmentSamples
是指向 VkSampleCountFlagBits 值数组的指针,这些值定义了颜色附件的采样计数。 -
depthStencilAttachmentSamples
是一个 VkSampleCountFlagBits 值,用于定义深度/模板附件的采样计数。
如果 VkCommandBufferInheritanceInfo::renderPass
为 VK_NULL_HANDLE,VkCommandBufferBeginInfo::flags
中指定了 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
,并且 VkCommandBufferInheritanceInfo 的 pNext
链包含 VkAttachmentSampleCountInfoAMD
,则此结构定义渲染通道实例中每个附件的采样计数。 如果未包含 VkAttachmentSampleCountInfoAMD
,则将 VkCommandBufferInheritanceRenderingInfo::rasterizationSamples
的值用作每个附件的采样计数。 如果 VkCommandBufferInheritanceInfo::renderPass
不为 VK_NULL_HANDLE,或者 VkCommandBufferBeginInfo::flags
中未指定 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
,则忽略此结构的参数。
VkAttachmentSampleCountInfoAMD
也可以包含在 VkGraphicsPipelineCreateInfo 的 pNext
链中。 当创建不带 VkRenderPass 的图形管线时,如果此结构包含在 VkGraphicsPipelineCreateInfo 的 pNext
链中,则它指定用于渲染的附件的采样计数。 如果未指定此结构,并且管线不包含 VkRenderPass,则将 VkPipelineMultisampleStateCreateInfo::rasterizationSamples
的值用作每个附件的采样计数。 如果使用有效的 VkRenderPass 创建图形管线,则忽略此结构的参数。
一旦开始录制,应用程序就会录制一系列命令 (vkCmd*
) 以在命令缓冲区中设置状态,绘制、调度和其他命令。
还可以从 VkBuffer
内容间接录制多个命令,请参阅 设备生成的命令。
要完成命令缓冲区的录制,请调用
// Provided by VK_VERSION_1_0
VkResult vkEndCommandBuffer(
VkCommandBuffer commandBuffer);
-
commandBuffer
是要完成录制的命令缓冲区。
如果在录制期间发生错误,应用程序将收到 vkEndCommandBuffer
返回的失败返回代码的通知,并且命令缓冲区将移动到 无效状态。
如果应用程序将一个或多个 视频编码操作录制到命令缓冲区中,如果任何指定的视频标准参数不符合所用视频压缩标准的语法或语义要求,或者如果根据所用视频压缩标准定义的规则从参数派生的值不符合视频压缩标准或实现的特性,则实现可能会返回 VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR
错误。
应用程序应不要依赖任何命令返回 |
当命令缓冲区处于可执行状态时,可以将其提交到队列以执行。
命令缓冲区提交
提交可能是一项高开销操作,应用程序应尝试将工作批量处理到尽可能少的对 |
要将命令缓冲区提交到队列,请调用
// Provided by VK_VERSION_1_3
VkResult vkQueueSubmit2(
VkQueue queue,
uint32_t submitCount,
const VkSubmitInfo2* pSubmits,
VkFence fence);
或者等效的命令
// Provided by VK_KHR_synchronization2
VkResult vkQueueSubmit2KHR(
VkQueue queue,
uint32_t submitCount,
const VkSubmitInfo2* pSubmits,
VkFence fence);
-
queue
是将要提交命令缓冲区的队列。 -
submitCount
是pSubmits
数组中元素的数量。 -
pSubmits
是指向 VkSubmitInfo2 结构数组的指针,每个结构指定一个命令缓冲区提交批处理。 -
fence
是一个可选的栅栏句柄,用于在所有提交的命令缓冲区完成执行后发出信号。 如果fence
不是 VK_NULL_HANDLE,则它定义一个栅栏信号操作。
vkQueueSubmit2
是一个队列提交命令,其中每个批次由 pSubmits
的一个元素定义。
与其它提交命令相比,使用 vkQueueSubmit2 提交的信号量操作具有额外的排序约束,涉及到先前和后续的队列操作。有关这些额外约束的信息,请参阅同步章节的信号量部分。
如果提交到此队列的任何命令缓冲区处于可执行状态,则它将移动到挂起状态。一旦命令缓冲区的所有提交执行完成,它将从挂起状态移回可执行状态。如果命令缓冲区在记录时使用了 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
标志,则它将移回无效状态。
如果 vkQueueSubmit2
失败,它可能会返回 VK_ERROR_OUT_OF_HOST_MEMORY
或 VK_ERROR_OUT_OF_DEVICE_MEMORY
。如果返回了这些错误,则实现必须确保提交的命令缓冲区引用的任何资源或同步原语的状态和内容,以及 pSubmits
引用的任何信号量不受此调用或其失败的影响。如果 vkQueueSubmit2
的失败导致实现无法做出此保证,则实现必须返回 VK_ERROR_DEVICE_LOST
。请参阅设备丢失。
VkSubmitInfo2
结构体定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkSubmitInfo2 {
VkStructureType sType;
const void* pNext;
VkSubmitFlags flags;
uint32_t waitSemaphoreInfoCount;
const VkSemaphoreSubmitInfo* pWaitSemaphoreInfos;
uint32_t commandBufferInfoCount;
const VkCommandBufferSubmitInfo* pCommandBufferInfos;
uint32_t signalSemaphoreInfoCount;
const VkSemaphoreSubmitInfo* pSignalSemaphoreInfos;
} VkSubmitInfo2;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkSubmitInfo2 VkSubmitInfo2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是 VkSubmitFlagBits 的位掩码。 -
waitSemaphoreInfoCount
是pWaitSemaphoreInfos
中的元素数量。 -
pWaitSemaphoreInfos
是一个指向 VkSemaphoreSubmitInfo 结构体数组的指针,用于定义信号量等待操作。 -
commandBufferInfoCount
是pCommandBufferInfos
中的元素数量,也是批处理中要执行的命令缓冲区数量。 -
pCommandBufferInfos
是一个指向 VkCommandBufferSubmitInfo 结构体数组的指针,用于描述批处理中要执行的命令缓冲区。 -
signalSemaphoreInfoCount
是pSignalSemaphoreInfos
中的元素数量。 -
pSignalSemaphoreInfos
是一个指向 VkSemaphoreSubmitInfo 结构体数组的指针,用于描述信号量信号操作。
在 VkSubmitInfo2::flags
中可以设置的位,用于指定提交行为,有:
// Provided by VK_VERSION_1_3
typedef enum VkSubmitFlagBits {
VK_SUBMIT_PROTECTED_BIT = 0x00000001,
// Provided by VK_KHR_synchronization2
VK_SUBMIT_PROTECTED_BIT_KHR = VK_SUBMIT_PROTECTED_BIT,
} VkSubmitFlagBits;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkSubmitFlagBits VkSubmitFlagBitsKHR;
-
VK_SUBMIT_PROTECTED_BIT
指定此批次是受保护的提交。
// Provided by VK_VERSION_1_3
typedef VkFlags VkSubmitFlags;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkSubmitFlags VkSubmitFlagsKHR;
VkSubmitFlags
是一个位掩码类型,用于设置零个或多个 VkSubmitFlagBits 的掩码。
VkSemaphoreSubmitInfo
结构体的定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkSemaphoreSubmitInfo {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
uint64_t value;
VkPipelineStageFlags2 stageMask;
uint32_t deviceIndex;
} VkSemaphoreSubmitInfo;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkSemaphoreSubmitInfo VkSemaphoreSubmitInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphore
是受此操作影响的 VkSemaphore。 -
value
要么是用于发出semaphore
信号的值,要么是semaphore
等待的值(如果semaphore
是时间线信号量)。否则,它将被忽略。 -
stageMask
是一个 VkPipelineStageFlags2 掩码,用于限制信号量信号操作的第一个同步范围,或信号量等待操作的第二个同步范围,如信号量等待操作和信号量信号操作章节中所述的同步章节。 -
deviceIndex
是设备组中执行信号量等待或信号操作的设备的索引。
此结构体定义信号量等待还是信号操作取决于其使用方式。
VkCommandBufferSubmitInfo
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkCommandBufferSubmitInfo {
VkStructureType sType;
const void* pNext;
VkCommandBuffer commandBuffer;
uint32_t deviceMask;
} VkCommandBufferSubmitInfo;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkCommandBufferSubmitInfo VkCommandBufferSubmitInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
commandBuffer
是要提交执行的 VkCommandBuffer。 -
deviceMask
是一个位掩码,指示设备组中的哪些设备执行命令缓冲区。deviceMask
为0
等效于将组中所有有效设备对应的位设置为1
。
VkRenderPassStripeSubmitInfoARM
结构定义如下:
// Provided by VK_ARM_render_pass_striped
typedef struct VkRenderPassStripeSubmitInfoARM {
VkStructureType sType;
const void* pNext;
uint32_t stripeSemaphoreInfoCount;
const VkSemaphoreSubmitInfo* pStripeSemaphoreInfos;
} VkRenderPassStripeSubmitInfoARM;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
stripeSemaphoreInfoCount
是用于在提交的命令缓冲区中的渲染通道实例中发出条纹完成信号的信号量的数量。 -
pStripeSemaphoreInfos
是一个指向stripeSemaphoreInfoCount
个 VkSemaphoreSubmitInfo 结构数组的指针,这些结构描述了用于发出条纹完成信号的信号量。
此结构可以包含在 VkCommandBufferSubmitInfo 的 pNext
链中,以便为每个条纹渲染通道实例提供一组要发出信号的信号量。
pStripeSemaphoreInfos
的元素按照提交顺序和每个渲染通道实例内的条纹顺序映射到 VkCommandBufferSubmitInfo::commandBuffer
中的渲染通道实例。当实现完成关联条纹的执行时,pStripeSemaphoreInfos
中的每个信号量都会发出信号。在启用了多视口的渲染通道实例中,条纹包括视图掩码中的所有视图。在 layerCount
大于 1 的渲染通道实例中,条纹包括所有层。
指定 VK_RENDERING_RESUMING_BIT
的渲染通道实例不会将 pStripeSemaphoreInfos
的任何元素映射到它们。相反,对于暂停和恢复渲染通道实例,此映射是为第一个暂停渲染通道实例完成的,并且仅为最后一个恢复渲染通道实例发出每个条纹信号量。
要将命令缓冲区提交到队列,请调用
// Provided by VK_VERSION_1_0
VkResult vkQueueSubmit(
VkQueue queue,
uint32_t submitCount,
const VkSubmitInfo* pSubmits,
VkFence fence);
-
queue
是将要提交命令缓冲区的队列。 -
submitCount
是pSubmits
数组中元素的数量。 -
pSubmits
是一个指向 VkSubmitInfo 结构数组的指针,每个结构都指定一个命令缓冲区提交批次。 -
fence
是一个可选的栅栏句柄,用于在所有提交的命令缓冲区完成执行后发出信号。 如果fence
不是 VK_NULL_HANDLE,则它定义一个栅栏信号操作。
vkQueueSubmit
是一个队列提交命令,每个批次由 pSubmits
的一个元素定义。批次按照它们在 pSubmits
中出现的顺序开始执行,但可能以无序的方式完成。
与其它提交命令相比,使用 vkQueueSubmit 提交的栅栏和信号量操作具有额外的排序约束,其中依赖项涉及先前和后续的队列操作。有关这些额外约束的信息,请参阅信号量和栅栏部分的同步章节。
如果提交到此队列的任何命令缓冲区处于可执行状态,则会将其移动到挂起状态。一旦命令缓冲区的所有提交执行完成,它将从挂起状态移回可执行状态。如果命令缓冲区在录制时使用了 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
标志,则它会移动到无效状态。
如果 vkQueueSubmit
失败,它可能返回 VK_ERROR_OUT_OF_HOST_MEMORY
或 VK_ERROR_OUT_OF_DEVICE_MEMORY
。如果返回了这些错误,则实现必须确保提交的命令缓冲区引用的任何资源或同步原语以及 pSubmits
引用的任何信号量的状态和内容不受该调用或其失败的影响。如果 vkQueueSubmit
的失败方式导致实现无法做出该保证,则实现必须返回 VK_ERROR_DEVICE_LOST
。请参阅设备丢失。
VkSubmitInfo
结构定义如下:
// Provided by VK_VERSION_1_0
typedef struct VkSubmitInfo {
VkStructureType sType;
const void* pNext;
uint32_t waitSemaphoreCount;
const VkSemaphore* pWaitSemaphores;
const VkPipelineStageFlags* pWaitDstStageMask;
uint32_t commandBufferCount;
const VkCommandBuffer* pCommandBuffers;
uint32_t signalSemaphoreCount;
const VkSemaphore* pSignalSemaphores;
} VkSubmitInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
waitSemaphoreCount
是在执行批处理的命令缓冲区之前需要等待的信号量的数量。 -
pWaitSemaphores
是一个指向 VkSemaphore 句柄数组的指针,在执行此批处理的命令缓冲区之前,需要等待这些句柄。 如果提供了需要等待的信号量,它们会定义一个 信号量等待操作。 -
pWaitDstStageMask
是一个指向管道阶段数组的指针,每个对应的信号量等待操作将发生在该管道阶段。 -
commandBufferCount
是要在此批处理中执行的命令缓冲区的数量。 -
pCommandBuffers
是一个指向要在批处理中执行的 VkCommandBuffer 句柄数组的指针。 -
signalSemaphoreCount
是在pCommandBuffers
中指定的命令执行完成后将要发出信号的信号量的数量。 -
pSignalSemaphores
是一个指向 VkSemaphore 句柄数组的指针,当此批处理的命令缓冲区执行完成后,将向这些句柄发出信号。 如果提供了要发出信号的信号量,它们会定义一个 信号量信号操作。
要指定在等待和发出使用 VK_SEMAPHORE_TYPE_TIMELINE
的 VkSemaphoreType 创建的信号量时使用的值,请在使用 vkQueueSubmit 时,将 VkTimelineSemaphoreSubmitInfo 结构添加到 VkSubmitInfo 结构的 pNext
链中,或者在使用 vkQueueBindSparse 时,将该结构添加到 VkBindSparseInfo 结构中。VkTimelineSemaphoreSubmitInfo
结构的定义如下:
// Provided by VK_VERSION_1_2
typedef struct VkTimelineSemaphoreSubmitInfo {
VkStructureType sType;
const void* pNext;
uint32_t waitSemaphoreValueCount;
const uint64_t* pWaitSemaphoreValues;
uint32_t signalSemaphoreValueCount;
const uint64_t* pSignalSemaphoreValues;
} VkTimelineSemaphoreSubmitInfo;
或等效的
// Provided by VK_KHR_timeline_semaphore
typedef VkTimelineSemaphoreSubmitInfo VkTimelineSemaphoreSubmitInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
waitSemaphoreValueCount
是在pWaitSemaphoreValues
中指定的信号量等待值的数量。 -
pWaitSemaphoreValues
是一个指针,指向一个包含waitSemaphoreValueCount
个值的数组,这些值对应于 VkSubmitInfo::pWaitSemaphores
中相应的信号量,用于等待。 -
signalSemaphoreValueCount
是在pSignalSemaphoreValues
中指定的信号量信号值的数量。 -
pSignalSemaphoreValues
是一个指针,指向一个包含signalSemaphoreValueCount
个值的数组,这些值对应于 VkSubmitInfo::pSignalSemaphores
中相应的信号量,在发出信号时设置。
如果 VkSubmitInfo::pWaitSemaphores
或 VkSubmitInfo::pSignalSemaphores
中的信号量对应于 pWaitSemaphoreValues
或 pSignalSemaphoreValues
中的条目,但该信号量不是使用 VK_SEMAPHORE_TYPE_TIMELINE
的 VkSemaphoreType 创建的,则实现必须忽略 pWaitSemaphoreValues
或 pSignalSemaphoreValues
条目中的值。
要指定在等待和发出其当前有效载荷引用 Direct3D 12 围栏的信号量时使用的值,请将 VkD3D12FenceSubmitInfoKHR 结构添加到 VkSubmitInfo 结构的 pNext
链中。VkD3D12FenceSubmitInfoKHR
结构的定义如下:
// Provided by VK_KHR_external_semaphore_win32
typedef struct VkD3D12FenceSubmitInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t waitSemaphoreValuesCount;
const uint64_t* pWaitSemaphoreValues;
uint32_t signalSemaphoreValuesCount;
const uint64_t* pSignalSemaphoreValues;
} VkD3D12FenceSubmitInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
waitSemaphoreValuesCount
是在pWaitSemaphoreValues
中指定的信号量等待值的数量。 -
pWaitSemaphoreValues
是一个指针,指向一个包含waitSemaphoreValuesCount
个值的数组,这些值对应于 VkSubmitInfo::pWaitSemaphores
中相应的信号量,用于等待。 -
signalSemaphoreValuesCount
是在pSignalSemaphoreValues
中指定的信号量信号值的数量。 -
pSignalSemaphoreValues
是一个指针,指向一个包含signalSemaphoreValuesCount
个值的数组,这些值对应于 VkSubmitInfo::pSignalSemaphores
中相应的信号量,在发出信号时设置。
如果 VkSubmitInfo::pWaitSemaphores
或 VkSubmitInfo::pSignalSemaphores
中的信号量对应于 pWaitSemaphoreValues
或 pSignalSemaphoreValues
中的条目,但该信号量当前没有引用 Direct3D 12 围栏的 有效载荷,则实现必须忽略 pWaitSemaphoreValues
或 pSignalSemaphoreValues
条目中的值。
由于外部信号量句柄类型 |
当向队列提交处理从 Direct3D 11 资源导入的内存的工作时,除了 Vulkan 信号量之外,还可以使用键控互斥机制来同步工作。键控互斥是正确创建的可共享 Direct3D 11 资源的属性。只有在导入的资源使用 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
标志创建时,才能使用它们。
要在提交的工作之前获取键控互斥锁和/或之后释放它们,请将 VkWin32KeyedMutexAcquireReleaseInfoKHR 结构添加到 VkSubmitInfo 结构的 pNext
链中。
VkWin32KeyedMutexAcquireReleaseInfoKHR
结构的定义如下:
// Provided by VK_KHR_win32_keyed_mutex
typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t acquireCount;
const VkDeviceMemory* pAcquireSyncs;
const uint64_t* pAcquireKeys;
const uint32_t* pAcquireTimeouts;
uint32_t releaseCount;
const VkDeviceMemory* pReleaseSyncs;
const uint64_t* pReleaseKeys;
} VkWin32KeyedMutexAcquireReleaseInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
acquireCount
是pAcquireSyncs
、pAcquireKeys
和pAcquireTimeouts
数组中的条目数。 -
pAcquireSyncs
是一个指向 VkDeviceMemory 对象数组的指针,这些对象是从 Direct3D 11 资源导入的。 -
pAcquireKeys
是一个指向互斥键值数组的指针,在开始提交的工作之前等待这些键值。这些条目引用与pAcquireSyncs
中相应条目关联的键控互斥锁。 -
pAcquireTimeouts
是一个指向超时值数组的指针,单位为毫秒,对应于pAcquireKeys
中指定的每个获取操作。 -
releaseCount
是pReleaseSyncs
和pReleaseKeys
数组中的条目数量。 -
pReleaseSyncs
是一个指向 VkDeviceMemory 对象数组的指针,这些对象是从 Direct3D 11 资源导入的。 -
pReleaseKeys
是一个指向互斥锁键值数组的指针,这些键值将在提交的工作完成后设置。条目引用与pReleaseSyncs
中相应条目关联的键控互斥锁。
当向队列提交处理从 Direct3D 11 资源导入的内存的工作时,除了 Vulkan 信号量之外,还可以使用键控互斥机制来同步工作。键控互斥是正确创建的可共享 Direct3D 11 资源的属性。只有在导入的资源使用 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
标志创建时,才能使用它们。
要在提交工作之前获取键控互斥锁,和/或在其之后释放它们,请将 VkWin32KeyedMutexAcquireReleaseInfoNV 结构添加到 VkSubmitInfo 结构的 pNext
链中。
VkWin32KeyedMutexAcquireReleaseInfoNV
结构的定义如下:
// Provided by VK_NV_win32_keyed_mutex
typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV {
VkStructureType sType;
const void* pNext;
uint32_t acquireCount;
const VkDeviceMemory* pAcquireSyncs;
const uint64_t* pAcquireKeys;
const uint32_t* pAcquireTimeoutMilliseconds;
uint32_t releaseCount;
const VkDeviceMemory* pReleaseSyncs;
const uint64_t* pReleaseKeys;
} VkWin32KeyedMutexAcquireReleaseInfoNV;
-
acquireCount
是pAcquireSyncs
、pAcquireKeys
和pAcquireTimeoutMilliseconds
数组中的条目数量。 -
pAcquireSyncs
是一个指向 VkDeviceMemory 对象数组的指针,这些对象是从 Direct3D 11 资源导入的。 -
pAcquireKeys
是一个指向互斥键值数组的指针,在开始提交的工作之前等待这些键值。这些条目引用与pAcquireSyncs
中相应条目关联的键控互斥锁。 -
pAcquireTimeoutMilliseconds
是一个指向超时值数组的指针,单位为毫秒,对应于pAcquireKeys
中指定的每个获取操作。 -
releaseCount
是pReleaseSyncs
和pReleaseKeys
数组中的条目数量。 -
pReleaseSyncs
是一个指向 VkDeviceMemory 对象数组的指针,这些对象是从 Direct3D 11 资源导入的。 -
pReleaseKeys
是一个指向互斥锁键值数组的指针,这些键值将在提交的工作完成后设置。条目引用与pReleaseSyncs
中相应条目关联的键控互斥锁。
如果 VkSubmitInfo 的 pNext
链包含 VkProtectedSubmitInfo
结构,则该结构指示批处理是否受保护。VkProtectedSubmitInfo
结构的定义如下:
// Provided by VK_VERSION_1_1
typedef struct VkProtectedSubmitInfo {
VkStructureType sType;
const void* pNext;
VkBool32 protectedSubmit;
} VkProtectedSubmitInfo;
-
protectedSubmit
指定批处理是否受保护。如果protectedSubmit
为VK_TRUE
,则该批处理受保护。如果protectedSubmit
为VK_FALSE
,则该批处理不受保护。如果VkSubmitInfo
::pNext
链不包含此结构,则该批处理不受保护。
如果 VkSubmitInfo 的 pNext
链包含 VkDeviceGroupSubmitInfo
结构,则该结构包含设备索引和掩码,指定哪些物理设备执行信号量操作和命令缓冲区。
VkDeviceGroupSubmitInfo
结构的定义如下:
// Provided by VK_VERSION_1_1
typedef struct VkDeviceGroupSubmitInfo {
VkStructureType sType;
const void* pNext;
uint32_t waitSemaphoreCount;
const uint32_t* pWaitSemaphoreDeviceIndices;
uint32_t commandBufferCount;
const uint32_t* pCommandBufferDeviceMasks;
uint32_t signalSemaphoreCount;
const uint32_t* pSignalSemaphoreDeviceIndices;
} VkDeviceGroupSubmitInfo;
或等效的
// Provided by VK_KHR_device_group
typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
waitSemaphoreCount
是pWaitSemaphoreDeviceIndices
数组中的元素数量。 -
pWaitSemaphoreDeviceIndices
是一个指向waitSemaphoreCount
个设备索引数组的指针,指示哪个物理设备在 VkSubmitInfo::pWaitSemaphores
的相应元素中执行信号量等待操作。 -
commandBufferCount
是pCommandBufferDeviceMasks
数组中的元素数量。 -
pCommandBufferDeviceMasks
是一个指向commandBufferCount
个设备掩码数组的指针,指示哪个物理设备在 VkSubmitInfo::pCommandBuffers
的相应元素中执行命令缓冲区。如果掩码中设置了相应的位,则物理设备执行命令缓冲区。 -
signalSemaphoreCount
是pSignalSemaphoreDeviceIndices
数组中的元素数量。 -
pSignalSemaphoreDeviceIndices
是一个指向signalSemaphoreCount
个设备索引数组的指针,指示哪个物理设备在 VkSubmitInfo::pSignalSemaphores
的相应元素中执行信号量信号操作。
如果不存在此结构,则信号量操作和命令缓冲区将在设备索引零上执行。
如果 VkSubmitInfo 的 pNext
链包含 VkPerformanceQuerySubmitInfoKHR 结构,则该结构指示该提交中批次活动的计数器通道。
VkPerformanceQuerySubmitInfoKHR
结构定义如下
// Provided by VK_KHR_performance_query
typedef struct VkPerformanceQuerySubmitInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t counterPassIndex;
} VkPerformanceQuerySubmitInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
counterPassIndex
指定哪个计数器通道索引是活动的。
如果 VkSubmitInfo
::pNext
链不包含此结构,则批次默认使用计数器通道索引 0。
队列前进进度
当使用二进制信号量时,应用程序必须确保命令缓冲区的提交可以在不进行应用程序在任何队列上的后续操作的情况下完成。在任何调用 vkQueueSubmit
(或其他队列操作)之后,对于每次在以 VkSemaphoreType 为 VK_SEMAPHORE_TYPE_BINARY
创建的信号量上排队的等待,必须存在对该信号量的先前信号,该信号不会被信号量上的不同等待消耗。
当使用时间线信号量时,先等待后发信号的行为是明确定义的,应用程序可以通过 vkQueueSubmit
提交工作,在提交相应的 信号量信号操作 之前定义 时间线信号量等待操作。对于每次由 vkQueueSubmit
调用定义的 时间线信号量等待操作,应用程序必须确保在可以取得进展之前执行相应的 信号量信号操作。
如果命令缓冲区提交等待任何事件被信号化,则应用程序必须确保命令缓冲区提交可以在不进行应用程序的任何后续操作的情况下完成。主机信号化的事件必须在命令缓冲区等待这些事件之前被信号化。
最初添加命令等待主机设置事件的功能是为了允许主机和设备之间资源的低延迟更新。但是,为了确保服务质量,实现将必须检测到执行中的长时间停顿并在短时间后超时。由于此时间段未在 Vulkan 规范中定义,因此无法正确验证任何具有任何等待时间的应用程序。由于此功能的原始用户非常有限且特定于平台,因此此功能现在被认为是失效的,不应使用。 |
二级命令缓冲区执行
二级命令缓冲区不得直接提交到队列。要记录一个二级命令缓冲区,作为主命令缓冲区的一部分执行,请调用
// Provided by VK_VERSION_1_0
void vkCmdExecuteCommands(
VkCommandBuffer commandBuffer,
uint32_t commandBufferCount,
const VkCommandBuffer* pCommandBuffers);
-
commandBuffer
是一个指向主命令缓冲区的句柄,二级命令缓冲区在该主命令缓冲区中执行。 -
commandBufferCount
是pCommandBuffers
数组的长度。 -
pCommandBuffers
是指向commandBufferCount
个二级命令缓冲区句柄数组的指针,这些句柄按照它们在数组中列出的顺序记录在主命令缓冲区中执行。
如果 pCommandBuffers
的任何元素未用 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT
标志记录,并且它被记录到当前处于可执行或录制状态的任何其他主命令缓冲区中,则该主命令缓冲区变为无效。
如果启用了 nestedCommandBuffer
功能,则将 vkCmdExecuteCommands
也记录到 二级命令缓冲区中是有效用法。
嵌套命令缓冲区
除了从主命令缓冲区执行辅助命令缓冲区之外,实现可以支持嵌套命令缓冲区,这使得可以从其他辅助命令缓冲区执行辅助命令缓冲区。如果启用了nestedCommandBuffer
特性,则该实现支持嵌套命令缓冲区。
嵌套命令缓冲区的执行方式与主到辅助的执行方式相同,但它受到一些额外的实现定义的限制。
每个辅助命令缓冲区都有一个命令缓冲区嵌套级别,该级别在vkEndCommandBuffer时确定,并在vkCmdExecuteCommands时评估。不执行任何其他辅助命令缓冲区的辅助命令缓冲区的命令缓冲区嵌套级别为零。否则,辅助命令缓冲区的命令缓冲区嵌套级别等于该命令缓冲区执行的所有辅助命令缓冲区的最大嵌套级别加一。某些实现可能对可以记录的辅助命令缓冲区的最大嵌套级别有限制。此限制在maxCommandBufferNestingLevel
中声明。
如果启用了nestedCommandBufferRendering
特性,则实现支持在记录了VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
的辅助命令缓冲区内调用vkCmdExecuteCommands。如果启用了nestedCommandBufferSimultaneousUse
特性,则实现支持使用记录了VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT
的辅助命令缓冲区调用vkCmdExecuteCommands。
每当在记录了 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
的辅助命令缓冲区内记录 vkCmdExecuteCommands 时,pCommandBuffers
的每个成员都必须已使用与正在记录 vkCmdExecuteCommands 调用的命令缓冲区的 VkCommandBufferInheritanceInfo 兼容的 VkCommandBufferBeginInfo 和 VkCommandBufferInheritanceInfo 记录。当 VkCommandBufferInheritanceRenderingInfo::renderpass
兼容时,或者如果它们是 VK_NULL_HANDLE,则 VkCommandBufferInheritanceRenderingInfo 成员匹配,并且 VkCommandBufferInheritanceRenderingInfo
的所有其他成员匹配,则 VkCommandBufferInheritanceRenderingInfo 结构兼容。此要求递归适用,从最嵌套的命令缓冲区到最初开始渲染通道的命令缓冲区。
命令缓冲区设备掩码
每个命令缓冲区都有一段状态存储命令缓冲区的当前设备掩码。此掩码控制逻辑设备内的哪些物理设备将执行所有后续命令,包括状态设置命令、操作命令和同步命令。
裁剪、独占裁剪和视口状态(不包括每个的计数)可以在每个物理设备上具有不同的值(仅在设置为动态状态时),并且每个物理设备将使用其状态的本地副本进行渲染。其他状态在物理设备之间共享,以便所有物理设备都使用最近设置的状态值。但是,当记录使用一段状态的操作命令时,设置该状态的最近命令必须在其当前设备掩码中包括执行操作命令的所有物理设备。
命令缓冲区的设备掩码与 VkDeviceGroupSubmitInfo 的 pCommandBufferDeviceMasks
成员正交。仅当在两个设备掩码中都设置了设备索引时,命令才会在物理设备上执行。
如果 VkCommandBufferBeginInfo 的 pNext
链包括一个 VkDeviceGroupCommandBufferBeginInfo
结构,则该结构包括命令缓冲区的初始设备掩码。
VkDeviceGroupCommandBufferBeginInfo
结构的定义如下
// Provided by VK_VERSION_1_1
typedef struct VkDeviceGroupCommandBufferBeginInfo {
VkStructureType sType;
const void* pNext;
uint32_t deviceMask;
} VkDeviceGroupCommandBufferBeginInfo;
或等效的
// Provided by VK_KHR_device_group
typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
deviceMask
是命令缓冲区的设备掩码的初始值。
初始设备掩码也充当命令缓冲区中设备掩码中可以出现的设备集的上限。
如果此结构不存在,则当命令缓冲区开始记录时,命令缓冲区的设备掩码的初始值包括逻辑设备中的所有物理设备。
要更新命令缓冲区的当前设备掩码,请调用
// Provided by VK_VERSION_1_1
void vkCmdSetDeviceMask(
VkCommandBuffer commandBuffer,
uint32_t deviceMask);
或者等效的命令
// Provided by VK_KHR_device_group
void vkCmdSetDeviceMaskKHR(
VkCommandBuffer commandBuffer,
uint32_t deviceMask);
-
commandBuffer
是当前设备掩码被修改的命令缓冲区。 -
deviceMask
是当前设备掩码的新值。
deviceMask
用于过滤掉未在掩码中设置位索引的所有物理设备上的后续命令执行,但是开始渲染通道实例的命令,转换到渲染通道实例中的下一个子通道的命令,以及结束渲染通道实例的命令除外,它们始终在物理设备集合上执行,这些物理设备的位索引包含在传递给开始相应渲染通道实例的命令的 VkDeviceGroupRenderPassBeginInfo 结构的 deviceMask
成员中。