同步和缓存控制
在 Vulkan 中,对资源的访问进行同步主要由应用程序负责。 命令相对于主机和其他设备上命令的执行顺序很少有隐式保证,需要显式指定。 内存缓存和其他优化也需要显式管理,这要求系统中的数据流很大程度上受应用程序控制。
虽然命令之间存在一些隐式保证,但 Vulkan 暴露了五种显式同步机制
- 栅栏
-
栅栏可以用于通知主机设备上的某些任务已完成执行,从而控制主机和设备之间的资源访问。
- 信号量
-
信号量可以用于控制多个队列之间的资源访问。
- 事件
-
事件提供了一种细粒度的同步原语,该原语可以在命令缓冲区内或由主机发出信号,并且可以在命令缓冲区内等待或在主机上查询。 事件可以用于控制单个队列中的资源访问。
- 管线屏障
-
管线屏障还在命令缓冲区内提供同步控制,但仅在一个点,而不是使用单独的信号和等待操作。 管线屏障可以用于控制单个队列中的资源访问。
- 渲染通道对象
-
渲染通道对象为渲染任务提供同步框架,该框架基于本章中的概念构建。 许多本来需要应用程序使用其他同步原语的情况,可以作为渲染通道的一部分更有效地表达。 渲染通道对象可以用于控制单个队列中的资源访问。
执行和内存依赖关系
操作是指在主机、设备或外部实体(例如呈现引擎)上执行的任意数量的工作。 同步命令在命令的两个同步范围定义的两组操作之间引入显式执行依赖关系和内存依赖关系。
同步范围定义了同步命令能够与之创建执行依赖关系的其他操作。 不在同步命令的同步范围内的任何类型的操作都不会包含在生成的依赖关系中。 例如,对于许多同步命令,同步范围可以限制为仅在特定管线阶段中执行的操作,这允许将其他管线阶段排除在依赖关系之外。 根据特定命令,可能会有其他作用域选项。
执行依赖关系保证对于两组操作,第一组操作必须在第二组操作之前发生。 如果一个操作在另一个操作之前发生,则第一个操作必须在第二个操作启动之前完成。 更准确地说
-
设 Ops1 和 Ops2 为单独的操作集。
-
设 Sync 为同步命令。
-
设 Scope1st 和 Scope2nd 为 Sync 的同步范围。
-
设 ScopedOps1 为集合 Ops1 和 Scope1st 的交集。
-
设 ScopedOps2 为集合 Ops2 和 Scope2nd 的交集。
-
按顺序提交 Ops1、Sync 和 Ops2 进行执行,将在 ScopedOps1 和 ScopedOps2 之间产生执行依赖关系 ExeDep。
-
执行依赖关系 ExeDep 保证 ScopedOps1 在 ScopedOps2 之前发生。
执行依赖关系链是执行依赖关系的序列,该序列在第一个依赖关系的 ScopedOps1 和最后一个依赖关系的 ScopedOps2 之间形成一个先发生关系。 对于每对连续的执行依赖关系,如果第一个依赖关系中的 Scope2nd 和第二个依赖关系中的 Scope1st 的交集不是空集,则存在链。 可以通过在执行依赖关系的描述中替换以下内容来描述从执行依赖关系链形成单个执行依赖关系
-
设 Sync 为生成执行依赖关系链的一组同步命令。
-
设 Scope1st 为 Sync 中第一个命令的第一个同步范围。
-
设 Scope2nd 为 Sync 中最后一个命令的第二个同步范围。
仅有执行依赖关系不足以保证从一个操作集中写入的值可以从另一个操作集中读取。
另外三种类型的操作用于控制内存访问。可用性操作使指定的内存写入访问生成的值对内存域可用,以便将来访问。任何可用的值都保持可用,直到后续对同一内存位置进行写入(无论是否使其可用)或内存被释放为止。内存域操作使对源内存域可用的写入对目标内存域可用(例如,使对主机域可用的写入对设备域可用)。可见性操作使对内存域可用的值对指定的内存访问可见。
可用性、可见性、内存域和内存域操作在 可用性和可见性 部分的 内存模型 章节中进行了正式定义。哪些 API 操作执行这些操作在 可用性、可见性和域操作 中定义。
内存依赖是一种执行依赖,它包括可用性和可见性操作,使得
-
第一组操作先于可用性操作发生。
-
可用性操作先于可见性操作发生。
-
可见性操作先于第二组操作发生。
一旦写入的值对特定类型的内存访问可见,它们可以被该类型的内存访问读取或写入。Vulkan 中的大多数同步命令都定义了内存依赖。
可用和可见的特定内存访问由内存依赖的访问范围定义。在内存依赖的第一个访问范围内的任何类型的访问,并且发生在 ScopedOps1 中的任何类型的访问都会被设为可用。在内存依赖的第二个访问范围内的任何类型的访问,并且发生在 ScopedOps2 中的任何类型的访问,都会使任何可用的写入对它可见。不在同步命令的访问范围内的任何类型的操作将不会包含在最终的依赖中。
内存依赖强制执行内存访问的可用性和可见性,以及两组操作之间的执行顺序。添加到 执行依赖链 的描述
-
令 MemOps1 为 ScopedOps1 执行的内存访问集合。
-
令 MemOps2 为 ScopedOps2 执行的内存访问集合。
-
令 AccessScope1st 为 Sync 链中第一个命令的第一个访问范围。
-
令 AccessScope2nd 为 Sync 链中最后一个命令的第二个访问范围。
-
令 ScopedMemOps1 为集合 MemOps1 和 AccessScope1st 的交集。
-
令 ScopedMemOps2 为集合 MemOps2 和 AccessScope2nd 的交集。
-
按照顺序提交 Ops1、Sync 和 Ops2 进行执行,将导致 ScopedOps1 和 ScopedOps2 之间存在内存依赖 MemDep。
-
内存依赖 MemDep 保证
-
ScopedMemOps1 中的内存写入被设为可用。
-
可用的内存写入(包括来自 ScopedMemOps1 的写入)对 ScopedMemOps2 可见。
-
执行依赖和内存依赖用于解决数据冲突,即确保读写操作以明确定义的顺序发生。先写后读冲突只需执行依赖即可解决,但先读后写和先写后写冲突需要在它们之间包含适当的内存依赖。如果应用程序不包含解决这些冲突的依赖,则内存访问的结果和执行顺序是未定义的。 |
图像布局转换
图像子资源可以作为 内存依赖 的一部分(例如,通过使用 图像内存屏障)从一个 布局 转换为另一个布局。当在内存依赖中指定布局转换时,它发生在内存依赖中的可用性操作之后,并且发生在可见性操作之前。图像布局转换可能对绑定到图像子资源范围的所有内存执行读写访问,因此应用程序必须确保所有内存写入在执行布局转换之前都已变为可用。可用的内存会自动对布局转换变为可见,并且布局转换执行的写入会自动变为可用。
布局转换始终应用于特定的图像子资源范围,并指定旧布局和新布局。旧布局必须是 VK_IMAGE_LAYOUT_UNDEFINED
,或者与图像子资源范围的当前布局匹配。如果旧布局与图像子资源范围的当前布局匹配,则转换会保留该范围的内容。如果旧布局是 VK_IMAGE_LAYOUT_UNDEFINED
,则该范围的内容可能会被丢弃。
使用 如果渲染过程完成后不需要附件的内容,则应用程序应该使用 |
由于图像布局转换可能对绑定到图像的内存执行读写访问,如果受布局转换影响的图像子资源绑定到当前设备掩码中任何设备的对等内存,则绑定内存来自的内存堆必须支持 vkGetDeviceGroupPeerMemoryFeatures 返回的 VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT
和 VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT
功能。
应用程序必须确保布局转换发生在所有使用旧布局访问图像的操作之后,并且发生在任何将使用新布局访问图像的操作之前。布局转换是潜在的读/写操作,因此如果不定义适当的内存依赖来保证这一点,将导致数据竞争。 |
图像布局转换与内存别名交互。
通过图像内存屏障执行的布局转换在 提交顺序 中完整执行,相对于提交到同一队列的其他图像布局转换,包括由渲染过程执行的转换。实际上,从每个这样的布局转换到之前提交到同一队列的所有布局转换都存在隐式的执行依赖。
使用 VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT
创建的深度/模板图像的每个图像子资源的图像布局,取决于上次渲染到该图像子资源作为深度/模板附件时使用的采样位置。因此,当 图像内存屏障 的 image
成员是使用此标志创建的图像时,应用程序可以将 VkSampleLocationsInfoEXT 结构链接到 VkImageMemoryBarrier2 或 VkImageMemoryBarrier 的 pNext
链,以指定在任何图像布局转换期间要使用的采样位置。
如果 VkSampleLocationsInfoEXT
结构与上次用于渲染到 subresourceRange
指定的图像子资源范围的采样位置状态不匹配,或者如果不存在 VkSampleLocationsInfoEXT
结构,则给定图像子资源范围的内容将变为未定义,如同 oldLayout
等于 VK_IMAGE_LAYOUT_UNDEFINED
一样。
管线阶段
操作命令 执行的工作由多个操作组成,这些操作以逻辑上独立的步骤序列执行,称为管线阶段。执行的确切管线阶段取决于所使用的特定命令,以及记录命令时当前的命令缓冲区状态。
一些同步命令包括管线阶段参数,将该命令的 同步范围 限制为仅这些阶段。这允许对操作命令执行的确切执行依赖性和访问进行精细控制。实现应该使用这些管线阶段以避免不必要的停顿或缓存刷新。
可以在 VkPipelineStageFlags2 掩码中设置的位,指定执行阶段,如下所示
// Provided by VK_VERSION_1_3
// Flag bits for VkPipelineStageFlagBits2
typedef VkFlags64 VkPipelineStageFlagBits2;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE = 0ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 0x00000001ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 0x00000002ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 0x00000004ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 0x00000008ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 0x00000040ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 0x00000080ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 0x00000100ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 0x00000200ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 0x00000800ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 0x00001000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT = 0x00001000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 0x00002000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT = 0x00004000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 0x00008000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 0x00010000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT = 0x100000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT = 0x200000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT = 0x400000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT = 0x800000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 0x1000000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 0x2000000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 0x4000000000ULL;
// Provided by VK_KHR_video_decode_queue
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0x04000000ULL;
// Provided by VK_KHR_video_encode_queue
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0x08000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE_KHR = 0ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_transform_feedback
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_conditional_rendering
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_device_generated_commands
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_device_generated_commands
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT = 0x00020000ULL;
// Provided by VK_KHR_fragment_shading_rate with VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_shading_rate_image
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000ULL;
// Provided by VK_KHR_acceleration_structure with VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000ULL;
// Provided by VK_KHR_ray_tracing_pipeline with VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_ray_tracing
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_ray_tracing
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_fragment_density_map
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_mesh_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_mesh_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_mesh_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT = 0x00080000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_mesh_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT = 0x00100000ULL;
// Provided by VK_HUAWEI_subpass_shading
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI = 0x8000000000ULL;
// VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI is a deprecated alias
// Provided by VK_HUAWEI_subpass_shading
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL;
// Provided by VK_HUAWEI_invocation_mask
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL;
// Provided by VK_KHR_ray_tracing_maintenance1 with VK_KHR_synchronization2 or VK_VERSION_1_3
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0x10000000ULL;
// Provided by VK_EXT_opacity_micromap
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT = 0x40000000ULL;
// Provided by VK_HUAWEI_cluster_culling_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI = 0x20000000000ULL;
// Provided by VK_NV_optical_flow
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV = 0x20000000ULL;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkPipelineStageFlagBits2 VkPipelineStageFlagBits2KHR;
-
VK_PIPELINE_STAGE_2_NONE
指定没有执行阶段。 -
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
指定使用间接命令参数的管线阶段。此阶段还包括读取由 vkCmdPreprocessGeneratedCommandsNV 写入的命令。此阶段还包括读取由 vkCmdPreprocessGeneratedCommandsEXT 写入的命令。 -
VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT
指定任务着色器阶段。 -
VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT
指定网格着色器阶段。 -
VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT
指定使用索引缓冲区的管线阶段。 -
VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT
指定使用顶点缓冲区的管线阶段。 -
VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT
等效于逻辑或-
VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT
-
VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT
-
-
VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
指定顶点着色器阶段。 -
VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT
指定细分控制着色器阶段。 -
VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT
指定细分评估着色器阶段。 -
VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT
指定几何着色器阶段。 -
VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT
等效于指定所有支持的预光栅化着色器阶段-
VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT
-
VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI
-
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
指定片段着色器阶段。 -
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
指定执行早期片段测试(片段着色之前的深度和模板测试)的管线阶段。此阶段还包括具有深度/模板格式的帧缓冲附件的渲染通道加载操作。 -
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
指定执行后期片段测试(片段着色之后的深度和模板测试)的管线阶段。此阶段还包括具有深度/模板格式的帧缓冲附件的渲染通道存储操作。 -
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
指定从管线输出最终颜色值的管线阶段。此阶段包括混合、逻辑操作、颜色附件的渲染通道加载和存储操作、渲染通道多重采样解析操作以及vkCmdClearAttachments。 -
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT
指定计算着色器阶段。 -
VK_PIPELINE_STAGE_2_HOST_BIT
指定伪阶段,表示在主机上执行设备内存的读取/写入。此阶段不会被命令缓冲区中记录的任何命令调用。 -
VK_PIPELINE_STAGE_2_COPY_BIT
指定所有 复制命令 的执行,包括 vkCmdCopyQueryPoolResults。 -
VK_PIPELINE_STAGE_2_BLIT_BIT
指定 vkCmdBlitImage 的执行。 -
VK_PIPELINE_STAGE_2_RESOLVE_BIT
指定 vkCmdResolveImage 的执行。 -
VK_PIPELINE_STAGE_2_CLEAR_BIT
指定清除命令的执行,除了vkCmdClearAttachments之外。 -
VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT
等效于指定所有-
VK_PIPELINE_STAGE_2_COPY_BIT
-
VK_PIPELINE_STAGE_2_BLIT_BIT
-
VK_PIPELINE_STAGE_2_RESOLVE_BIT
-
VK_PIPELINE_STAGE_2_CLEAR_BIT
-
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR
-
-
VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR
指定光线追踪着色器阶段的执行。 -
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
指定加速结构命令或加速结构复制命令的执行。 -
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR
指定执行加速结构复制命令。 -
VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
指定执行所有图形管线阶段,等效于以下各项的逻辑或:-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT
-
VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT
-
VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
-
VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT
-
VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
-
VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT
-
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
-
VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI
-
VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI
-
-
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT
指定与其一起使用的队列上支持的所有命令执行的所有操作。 -
VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT
指定管线中消耗条件渲染谓词的阶段。 -
VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
指定管线中将顶点属性输出值写入变换反馈缓冲区的阶段。 -
VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV
指定管线中通过 vkCmdPreprocessGeneratedCommandsNV 处理设备端命令生成的阶段。 -
VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT
指定管线中通过 vkCmdPreprocessGeneratedCommandsEXT 处理设备端命令生成的阶段。 -
VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
指定管线中读取片元着色率附件或着色率图像以确定光栅化图元部分片元着色率的阶段。 -
VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT
指定管线中读取片元密度图以生成片元区域的阶段。 -
VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI
指定管线中实现读取调用掩码图像以优化射线调度的阶段。 -
VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR
指定执行视频解码操作。 -
VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR
指定执行视频编码操作。 -
VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV
指定管线中执行光流操作的阶段。 -
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
指定子通道着色器阶段。 -
VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT
指定执行微映射命令。 -
VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI
指定集群剔除着色器阶段。 -
VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT
等效于VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT
,当在第二个同步作用域中指定时,VkAccessFlags2 设置为0
,但在第一个作用域中等效于VK_PIPELINE_STAGE_2_NONE
。 -
VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT
等效于VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT
,当在第一个同步作用域中指定时,VkAccessFlags2 设置为0
,但在第二个作用域中等效于VK_PIPELINE_STAGE_2_NONE
。
|
|
VkPipelineStageFlags2
是一种位掩码类型,用于设置零个或多个 VkPipelineStageFlagBits2 标志的掩码
// Provided by VK_VERSION_1_3
typedef VkFlags64 VkPipelineStageFlags2;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkPipelineStageFlags2 VkPipelineStageFlags2KHR;
可以在 VkPipelineStageFlags 掩码中设置的位,指定执行阶段,包括
// Provided by VK_VERSION_1_0
typedef enum VkPipelineStageFlagBits {
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001,
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008,
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010,
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020,
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100,
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800,
VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000,
VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
// Provided by VK_VERSION_1_3
VK_PIPELINE_STAGE_NONE = 0,
// Provided by VK_EXT_transform_feedback
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000,
// Provided by VK_EXT_conditional_rendering
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000,
// Provided by VK_KHR_acceleration_structure
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000,
// Provided by VK_KHR_ray_tracing_pipeline
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000,
// Provided by VK_EXT_fragment_density_map
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000,
// Provided by VK_KHR_fragment_shading_rate
VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000,
// Provided by VK_NV_device_generated_commands
VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000,
// Provided by VK_EXT_mesh_shader
VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT = 0x00080000,
// Provided by VK_EXT_mesh_shader
VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT = 0x00100000,
// Provided by VK_NV_shading_rate_image
VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR,
// Provided by VK_NV_ray_tracing
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
// Provided by VK_NV_ray_tracing
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
// Provided by VK_NV_mesh_shader
VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT,
// Provided by VK_NV_mesh_shader
VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT,
// Provided by VK_KHR_synchronization2
VK_PIPELINE_STAGE_NONE_KHR = VK_PIPELINE_STAGE_NONE,
// Provided by VK_EXT_device_generated_commands
VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT = VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV,
} VkPipelineStageFlagBits;
这些值都具有与 VkPipelineStageFlags2 的等效命名值相同的含义。
-
VK_PIPELINE_STAGE_NONE
指定没有执行阶段。 -
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
指定管线中消耗VkDrawIndirect*
/VkDispatchIndirect*
/VkTraceRaysIndirect*
数据结构的阶段。此阶段还包括读取由 vkCmdExecuteGeneratedCommandsNV 写入的命令。此阶段还包括读取由 vkCmdExecuteGeneratedCommandsEXT 写入的命令。 -
VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT
指定任务着色器阶段。 -
VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT
指定网格着色器阶段。 -
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
指定管线中消耗顶点和索引缓冲区的阶段。 -
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
指定顶点着色器阶段。 -
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
指定细分控制着色器阶段。 -
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
指定细分评估着色器阶段。 -
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
指定几何着色器阶段。 -
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
指定片元着色器阶段。 -
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
指定管线中执行早期片元测试(在片元着色之前的深度和模板测试)的阶段。此阶段还包括具有深度/模板格式的帧缓冲附件的渲染通道加载操作。 -
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
指定管线中执行后期片元测试(在片元着色之后的深度和模板测试)的阶段。此阶段还包括具有深度/模板格式的帧缓冲附件的渲染通道存储操作。 -
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
指定混合后管线输出最终颜色值的管线阶段。此阶段包括混合、逻辑操作,用于颜色附件的渲染通道加载和存储操作、渲染通道多采样解析操作以及vkCmdClearAttachments。 -
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
指定计算着色器的执行。 -
VK_PIPELINE_STAGE_HOST_BIT
指定一个伪阶段,指示主机上对设备内存的读取/写入的执行。 此阶段不由命令缓冲区中记录的任何命令调用。 -
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
指定执行 vkCmdBuildAccelerationStructureNV、vkCmdCopyAccelerationStructureNV、vkCmdWriteAccelerationStructuresPropertiesNV、vkCmdBuildAccelerationStructuresKHR、vkCmdBuildAccelerationStructuresIndirectKHR、vkCmdCopyAccelerationStructureKHR、vkCmdCopyAccelerationStructureToMemoryKHR、vkCmdCopyMemoryToAccelerationStructureKHR 和 vkCmdWriteAccelerationStructuresPropertiesKHR。 -
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR
指定通过 vkCmdTraceRaysNV、vkCmdTraceRaysKHR 或 vkCmdTraceRaysIndirectKHR 执行的光线追踪着色器阶段。 -
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
指定所有图形管线阶段的执行,等效于以下各项的逻辑或:-
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
-
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
-
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
-
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
-
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
-
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
-
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT
-
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
-
VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
-
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
-
-
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
指定在与其一起使用的队列上支持的所有命令执行的所有操作。 -
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT
指定管线中消耗条件渲染谓词的阶段。 -
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
指定管线中将顶点属性输出值写入变换反馈缓冲区的阶段。 -
VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV
指定管线中通过 vkCmdPreprocessGeneratedCommandsNV 处理为生成命令的设备端预处理的阶段。 -
VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT
指定管线中通过 vkCmdPreprocessGeneratedCommandsEXT 处理为生成命令的设备端预处理的阶段。 -
VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
指定管线中读取片段着色率附件或着色率图像以确定光栅化图元的各个部分的片段着色率的阶段。 -
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
指定管线中读取片段密度图以生成片段区域的阶段。 -
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
等效于VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,当在第二个同步范围中指定时,VkAccessFlags 设置为0
,但在第一个范围中指定时不指定任何执行阶段。 -
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
等效于VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,当在第一个同步范围中指定时,VkAccessFlags 设置为0
,但在第二个范围中指定时不指定任何执行阶段。
// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineStageFlags;
VkPipelineStageFlags
是一种位掩码类型,用于设置零个或多个 VkPipelineStageFlagBits 的掩码。
请注意,访问范围不会与任何一个范围的逻辑上更早或更晚的阶段交互 - 仅考虑应用程序指定的阶段是每个访问范围的一部分。 |
某些管线阶段仅在支持特定操作集的队列上可用。下表列出了每个管线阶段标志,队列必须支持哪个队列功能标志。当表的第二列中枚举多个标志时,这意味着如果队列支持任何列出的功能标志,则支持该管线阶段。有关队列功能的更多详细信息,请参阅 物理设备枚举 和 队列。
管线阶段标志 | 所需的队列功能标志 |
---|---|
|
无要求 |
|
无要求 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
无要求 |
|
无要求 |
|
|
|
无要求 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
作为命令结果执行的管线阶段在逻辑上按特定顺序完成执行,以便逻辑上更晚的管线阶段的完成必须在逻辑上更早的阶段完成之前发生。这意味着在特定同步命令的源阶段掩码中包含任何阶段也意味着该命令的 Scope1st 中也包含任何逻辑上更早的阶段。
类似地,逻辑上较早的管线阶段的启动必须不能发生在逻辑上较晚的管线阶段的启动之后。对于特定的同步命令,将任何给定的阶段包括在目标阶段掩码中,也意味着任何逻辑上较晚的阶段都包含在该命令的 Scope2nd 中。
实现可能不支持对每个同步操作的每个管线阶段进行同步。如果实现不支持同步的管线阶段出现在源阶段掩码中,则它可能用任何逻辑上较晚的阶段来代替它,用于第一个同步范围。如果实现不支持同步的管线阶段出现在目标阶段掩码中,则它可能用任何逻辑上较早的阶段来代替它,用于第二个同步范围。 例如,如果实现无法在顶点着色器执行完成后立即发出事件信号,则它可能改为在颜色附件输出完成后发出事件信号。 如果实现进行了这样的替换,则必须不影响执行或内存依赖关系或图像和缓冲区内存屏障的语义。 |
图形管线在支持 VK_QUEUE_GRAPHICS_BIT
的队列上执行。图形管线执行的阶段只能在为支持 VK_QUEUE_GRAPHICS_BIT
的队列记录的命令中指定。
图形图元管线执行以下阶段,阶段的逻辑顺序与此处指定的顺序匹配
-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT
-
VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT
-
VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT
-
VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
-
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
图形网格管线执行以下阶段,阶段的逻辑顺序与此处指定的顺序匹配
-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
-
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
对于计算管线,以下阶段按此顺序发生
-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT
对于子通道着色管线,以下阶段按此顺序发生
-
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
对于在具有片段密度图附件的渲染通道中执行的图形管线命令,读取片段密度图的以下管线阶段相对于其他阶段没有特定的顺序,但它在逻辑上比 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
早。
-
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
-
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
条件渲染阶段正式属于图形管线和计算管线的一部分。读取谓词的管线阶段相对于这些管线的其他阶段具有未指定的顺序
-
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT
对于传输管线,以下阶段按此顺序发生
-
VK_PIPELINE_STAGE_2_TRANSFER_BIT
对于主机操作,只发生一个管线阶段,因此不保证顺序
-
VK_PIPELINE_STAGE_2_HOST_BIT
对于命令预处理管线,以下阶段按此顺序发生
-
VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT
对于加速结构构建操作,只发生一个管线阶段,因此不保证顺序
-
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
对于加速结构复制操作,只发生一个管线阶段,因此不保证顺序
-
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR
对于不透明度微型地图构建操作,只发生一个管线阶段,因此不保证顺序
-
VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT
对于光线追踪管线,以下阶段按此顺序发生
-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR
对于视频解码管线,以下阶段按此顺序发生
-
VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR
对于视频编码管线,以下阶段按此顺序发生
-
VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR
访问类型
Vulkan 中的内存可以从着色器调用中访问,也可以通过管线的一些固定功能阶段访问。访问类型是使用的 描述符类型 的函数,或固定功能阶段如何访问内存的函数。
一些同步命令将一组访问类型作为参数,以定义内存依赖项的访问范围。如果同步命令包含源访问掩码,则其第一个访问范围仅包含通过该掩码中指定的访问类型进行的访问。类似地,如果同步命令包含目标访问掩码,则其第二个访问范围仅包含通过该掩码中指定的访问类型进行的访问。
可以在 VkMemoryBarrier2KHR、VkImageMemoryBarrier2KHR 和 VkBufferMemoryBarrier2KHR 的 srcAccessMask
和 dstAccessMask
成员中设置的位,指定访问行为,是
// Provided by VK_VERSION_1_3
// Flag bits for VkAccessFlagBits2
typedef VkFlags64 VkAccessFlagBits2;
static const VkAccessFlagBits2 VK_ACCESS_2_NONE = 0ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 0x00000001ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT = 0x00000002ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT = 0x00000008ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 0x00000010ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT = 0x00000020ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT = 0x00000040ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 0x00000080ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT = 0x00000800ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT = 0x00001000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT = 0x00002000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT = 0x00004000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT = 0x00008000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT = 0x00010000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 0x100000000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 0x200000000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 0x400000000ULL;
// Provided by VK_KHR_video_decode_queue
static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL;
// Provided by VK_KHR_video_decode_queue
static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL;
// Provided by VK_KHR_video_encode_queue
static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL;
// Provided by VK_KHR_video_encode_queue
static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_NONE_KHR = 0ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_transform_feedback
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_transform_feedback
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_transform_feedback
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_conditional_rendering
static const VkAccessFlagBits2 VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_device_generated_commands
static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_device_generated_commands
static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_device_generated_commands
static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_EXT = 0x00020000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_device_generated_commands
static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_EXT = 0x00040000ULL;
// Provided by VK_KHR_fragment_shading_rate with VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_shading_rate_image
static const VkAccessFlagBits2 VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000ULL;
// Provided by VK_KHR_acceleration_structure with VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000ULL;
// Provided by VK_KHR_acceleration_structure with VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_ray_tracing
static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_ray_tracing
static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_fragment_density_map
static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_blend_operation_advanced
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000ULL;
// Provided by VK_EXT_descriptor_buffer
static const VkAccessFlagBits2 VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT = 0x20000000000ULL;
// Provided by VK_HUAWEI_invocation_mask
static const VkAccessFlagBits2 VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0x8000000000ULL;
// Provided by VK_KHR_ray_tracing_maintenance1 with (VK_KHR_synchronization2 or VK_VERSION_1_3) and VK_KHR_ray_tracing_pipeline
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR = 0x10000000000ULL;
// Provided by VK_EXT_opacity_micromap
static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_READ_BIT_EXT = 0x100000000000ULL;
// Provided by VK_EXT_opacity_micromap
static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT = 0x200000000000ULL;
// Provided by VK_NV_optical_flow
static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV = 0x40000000000ULL;
// Provided by VK_NV_optical_flow
static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV = 0x80000000000ULL;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkAccessFlagBits2 VkAccessFlagBits2KHR;
-
VK_ACCESS_2_NONE
指定没有访问。 -
VK_ACCESS_2_MEMORY_READ_BIT
指定所有读取访问。它在任何访问掩码中始终有效,并且被视为等效于设置所有在它使用的地方有效的READ
访问标志。 -
VK_ACCESS_2_MEMORY_WRITE_BIT
指定所有写入访问。它在任何访问掩码中始终有效,并且被视为等效于设置所有在它使用的地方有效的WRITE
访问标志。 -
VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT
指定读取从间接缓冲区读取的命令数据的访问,作为间接构建、跟踪、绘制或调度命令的一部分。此类访问发生在VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
管线阶段。 -
VK_ACCESS_2_INDEX_READ_BIT
指定读取索引缓冲区的访问,作为由 vkCmdBindIndexBuffer2 和 vkCmdBindIndexBuffer 绑定的索引绘制命令的一部分。此类访问发生在VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT
管线阶段。 -
VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT
指定读取顶点缓冲区的访问,作为由 vkCmdBindVertexBuffers 绑定的绘制命令的一部分。此类访问发生在VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT
管线阶段。 -
VK_ACCESS_2_UNIFORM_READ_BIT
指定读取任何着色器管线阶段中的统一缓冲区的访问。 -
VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT
指定读取渲染通道中子通道着色或片段着色期间的输入附件的访问。此类访问发生在VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
或VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
管线阶段。 -
VK_ACCESS_2_SHADER_SAMPLED_READ_BIT
指定读取任何着色器管线阶段中的统一纹理缓冲区或采样图像的访问。 -
VK_ACCESS_2_SHADER_STORAGE_READ_BIT
指定读取任何着色器管线阶段中的存储缓冲区、物理存储缓冲区、存储纹理缓冲区或存储图像的访问。 -
VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR
指定读取任何着色器管线阶段中的着色器绑定表的访问。 -
VK_ACCESS_2_SHADER_READ_BIT
等价于以下各项的逻辑或:-
VK_ACCESS_2_SHADER_SAMPLED_READ_BIT
-
VK_ACCESS_2_SHADER_STORAGE_READ_BIT
-
-
VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT
指定在任何着色器管线阶段对存储缓冲区、物理存储缓冲区、存储纹理缓冲或存储图像的写入访问。 -
VK_ACCESS_2_SHADER_WRITE_BIT
等价于VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT
。 -
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT
指定对颜色附件的读取访问,例如通过混合(除了高级混合操作)、逻辑操作或VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
管线阶段中的某些渲染通道加载操作,或通过VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
管线阶段中的片段着色器瓦片图像读取。 -
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT
指定在渲染通道期间或通过某些渲染通道的加载、存储和多采样解析操作对颜色附件的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
管线阶段。 -
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT
指定对深度/模板附件的读取访问,通过深度或模板操作或VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
或VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
管线阶段中的某些渲染通道加载操作,或通过VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
管线阶段中的片段着色器瓦片图像读取。 -
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
指定通过深度或模板操作或某些渲染通道的加载和存储操作,对深度/模板附件的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
或VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
管线阶段。 -
VK_ACCESS_2_TRANSFER_READ_BIT
指定在复制操作中对图像或缓冲区的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_COPY_BIT
、VK_PIPELINE_STAGE_2_BLIT_BIT
或VK_PIPELINE_STAGE_2_RESOLVE_BIT
管线阶段。 -
VK_ACCESS_2_TRANSFER_WRITE_BIT
指定在清除或复制操作中对图像或缓冲区的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_COPY_BIT
、VK_PIPELINE_STAGE_2_BLIT_BIT
、VK_PIPELINE_STAGE_2_CLEAR_BIT
或VK_PIPELINE_STAGE_2_RESOLVE_BIT
管线阶段。 -
VK_ACCESS_2_HOST_READ_BIT
指定主机操作的读取访问。这种类型的访问不是通过资源执行的,而是直接在内存上执行的。这种访问发生在VK_PIPELINE_STAGE_2_HOST_BIT
管线阶段。 -
VK_ACCESS_2_HOST_WRITE_BIT
指定主机操作的写入访问。这种类型的访问不是通过资源执行的,而是直接在内存上执行的。这种访问发生在VK_PIPELINE_STAGE_2_HOST_BIT
管线阶段。 -
VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT
指定作为条件渲染一部分对谓词的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT
管线阶段。 -
VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
指定当变换反馈处于活动状态时对变换反馈缓冲区的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
管线阶段。 -
VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
指定在执行 vkCmdBeginTransformFeedbackEXT 时读取的变换反馈计数器缓冲区的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
管线阶段。 -
VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT
指定在执行 vkCmdEndTransformFeedbackEXT 时写入的变换反馈计数器缓冲区的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
管线阶段。 -
VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV
指定从 vkCmdPreprocessGeneratedCommandsNV 的缓冲区输入中读取。这种访问发生在VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV
管线阶段。 -
VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV
指定写入到目标命令缓冲区预处理输出。这种访问发生在VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV
管线阶段。 -
VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_EXT
指定从 vkCmdPreprocessGeneratedCommandsEXT 的缓冲区输入中读取。这种访问发生在VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT
管线阶段。 -
VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_EXT
指定写入到目标命令缓冲区预处理输出。这种访问发生在VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT
管线阶段。 -
VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT
指定对颜色附件的读取访问,包括高级混合操作。这种访问发生在VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
管线阶段。 -
VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI
指定在VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI
管线阶段中对调用掩码图像的读取访问。 -
VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR
指定对加速结构的读取访问,作为跟踪、构建或复制命令的一部分,或者作为构建命令一部分对加速结构暂存缓冲区的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR
管线阶段或VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段。 -
VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR
指定对加速结构或加速结构暂存缓冲区的写入访问,作为构建或复制命令的一部分。这种访问发生在VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段。 -
VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT
指定在动态片段密度图操作期间对片段密度图附件的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT
管线阶段。 -
VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR
指定在光栅化期间对片段着色率附件的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
管线阶段。 -
VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV
指定在光栅化期间对着色率图像的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV
管线阶段。它等价于VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR
。 -
VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR
指定在视频解码操作中对图像或缓冲区资源的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR
管线阶段。 -
VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR
指定在视频解码操作中对图像或缓冲区资源的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR
管线阶段。 -
VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR
指定在视频编码操作中对图像或缓冲区资源的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR
管线阶段。 -
VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR
指定在视频编码操作中对图像或缓冲区资源的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR
管线阶段。 -
VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT
指定在任何着色器管线阶段中对描述符缓冲区的读取访问。 -
VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV
指定在光流操作中对图像或缓冲区资源的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV
管线阶段。 -
VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV
指定在光流操作中对图像或缓冲区资源的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV
管线阶段。 -
VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT
指定对微型地图对象的写入访问。这种访问发生在VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT
管线阶段。 -
VK_ACCESS_2_MICROMAP_READ_BIT_EXT
指定对微型地图对象的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT
和VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段。
在应用程序希望为给定的一组管线阶段选择所有访问类型的情况下,可以使用 |
|
VkAccessFlags2
是一种位掩码类型,用于设置零个或多个 VkAccessFlagBits2 的掩码
// Provided by VK_VERSION_1_3
typedef VkFlags64 VkAccessFlags2;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkAccessFlags2 VkAccessFlags2KHR;
应用程序 **可以** 在 VkMemoryBarrier2、VkBufferMemoryBarrier2 或 VkImageMemoryBarrier2 的 pNext
链中链接一个 VkMemoryBarrierAccessFlags3KHR 结构,以提供 VkAccessFlagBits2 中未提供的额外访问标志。
VkMemoryBarrierAccessFlags3KHR
结构定义如下
// Provided by VK_KHR_maintenance8
typedef struct VkMemoryBarrierAccessFlags3KHR {
VkStructureType sType;
const void* pNext;
VkAccessFlags3KHR srcAccessMask3;
VkAccessFlags3KHR dstAccessMask3;
} VkMemoryBarrierAccessFlags3KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcAccessMask3
是一个 VkAccessFlags3KHR 掩码,其中包含要包含在第一个访问范围中的访问标志。 -
dstAccessMask3
是一个 VkAccessFlags3KHR 掩码,其中包含要包含在第二个访问范围中的访问标志。
在 VkMemoryBarrierAccessFlags3KHR 的 srcAccessMask3
和 dstAccessMask3
成员中 **可以** 设置的位,用于指定访问行为,如下所示
// Provided by VK_KHR_maintenance8
// Flag bits for VkAccessFlagBits3KHR
typedef VkFlags64 VkAccessFlagBits3KHR;
static const VkAccessFlagBits3KHR VK_ACCESS_3_NONE_KHR = 0ULL;
-
VK_ACCESS_3_NONE_KHR
指定没有额外的访问。
VkAccessFlags3KHR
是一种位掩码类型,用于设置零个或多个 VkAccessFlagBits3KHR 的掩码
// Provided by VK_KHR_maintenance8
typedef VkFlags64 VkAccessFlags3KHR;
当 VkMemoryBarrierAccessFlags3KHR 结构链接到 VkMemoryBarrier2、VkBufferMemoryBarrier2 或 VkImageMemoryBarrier2 的 pNext
字段中时,将考虑 srcAccessMask3
和 dstAccessMask3
字段中指定的标志,以及 srcAccessMask
和 dstAccessMask
字段中的标志,以便允许为第一个或第二个访问范围最多指定 128 种总访问类型。
注意
当 VkAccessFlagBits3KHR 和 VkAccessFlagBits2 一起使用时,这两组 64 个标志位组合成 128 个标志位(实际上是将它们进行或运算)。这与 VkAccessFlagBits2 和 VkAccessFlagBits 不同,其中 64 位 VkAccessFlagBits2 扩展并 *替换* 了 32 位 VkAccessFlagBits。 |
在 VkSubpassDependency、VkSubpassDependency2、VkMemoryBarrier、VkBufferMemoryBarrier 和 VkImageMemoryBarrier 的 srcAccessMask
和 dstAccessMask
成员中 **可以** 设置的位,用于指定访问行为,如下所示
// Provided by VK_VERSION_1_0
typedef enum VkAccessFlagBits {
VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001,
VK_ACCESS_INDEX_READ_BIT = 0x00000002,
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004,
VK_ACCESS_UNIFORM_READ_BIT = 0x00000008,
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010,
VK_ACCESS_SHADER_READ_BIT = 0x00000020,
VK_ACCESS_SHADER_WRITE_BIT = 0x00000040,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400,
VK_ACCESS_TRANSFER_READ_BIT = 0x00000800,
VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000,
VK_ACCESS_HOST_READ_BIT = 0x00002000,
VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
// Provided by VK_VERSION_1_3
VK_ACCESS_NONE = 0,
// Provided by VK_EXT_transform_feedback
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000,
// Provided by VK_EXT_transform_feedback
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000,
// Provided by VK_EXT_transform_feedback
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000,
// Provided by VK_EXT_conditional_rendering
VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000,
// Provided by VK_EXT_blend_operation_advanced
VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000,
// Provided by VK_KHR_acceleration_structure
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000,
// Provided by VK_KHR_acceleration_structure
VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000,
// Provided by VK_EXT_fragment_density_map
VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000,
// Provided by VK_KHR_fragment_shading_rate
VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000,
// Provided by VK_NV_device_generated_commands
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000,
// Provided by VK_NV_device_generated_commands
VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000,
// Provided by VK_NV_shading_rate_image
VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
// Provided by VK_NV_ray_tracing
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
// Provided by VK_NV_ray_tracing
VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
// Provided by VK_KHR_synchronization2
VK_ACCESS_NONE_KHR = VK_ACCESS_NONE,
// Provided by VK_EXT_device_generated_commands
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT = VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV,
// Provided by VK_EXT_device_generated_commands
VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT = VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV,
} VkAccessFlagBits;
这些值都具有与 VkAccessFlags2 的等效命名值相同的含义。
-
VK_ACCESS_NONE
指定无访问。 -
VK_ACCESS_MEMORY_READ_BIT
指定所有读取访问。它在任何访问掩码中始终有效,并且被视为等效于设置所有在其使用位置有效的READ
访问标志。 -
VK_ACCESS_MEMORY_WRITE_BIT
指定所有写入访问。它在任何访问掩码中始终有效,并且被视为等效于设置所有在其使用位置有效的WRITE
访问标志。 -
VK_ACCESS_INDIRECT_COMMAND_READ_BIT
指定对间接命令数据的读取访问,该数据作为间接构建、跟踪、绘制或调度命令的一部分读取。这种访问发生在VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
管线阶段。 -
VK_ACCESS_INDEX_READ_BIT
指定对索引缓冲区的读取访问,该缓冲区作为索引绘制命令的一部分,由 vkCmdBindIndexBuffer2 和 vkCmdBindIndexBuffer 绑定。这种访问发生在VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
管线阶段。 -
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
指定对顶点缓冲区的读取访问,该缓冲区作为绘制命令的一部分,由 vkCmdBindVertexBuffers 绑定。这种访问发生在VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
管线阶段。 -
VK_ACCESS_UNIFORM_READ_BIT
指定在任何着色器管线阶段中对uniform 缓冲区的读取访问。 -
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
指定在子通道着色或片段着色期间,在渲染通道内对输入附件的读取访问。这种访问发生在VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
或VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
管线阶段。 -
VK_ACCESS_SHADER_READ_BIT
指定在任何着色器管线阶段对uniform texel buffer、采样图像、存储缓冲区、物理存储缓冲区、着色器绑定表、存储纹理缓冲区或存储图像的读取访问权限。 -
VK_ACCESS_SHADER_WRITE_BIT
指定在任何着色器管线阶段对存储缓冲区、物理存储缓冲区、存储纹理缓冲区或存储图像的写入访问权限。 -
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
指定在VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
管线阶段,通过混合(除了高级混合操作之外)、逻辑操作或某些渲染通道加载操作,或者在VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
管线阶段通过片段着色器 tile 图像读取对颜色附件的读取访问权限。 -
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
指定在渲染通道期间,或者通过某些渲染通道的加载和存储操作,对颜色、解析或深度/模板解析附件的写入访问权限。这种访问发生在VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
管线阶段。 -
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
指定在VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
或VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
管线阶段,通过深度或模板操作或某些渲染通道加载操作,或者在VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
管线阶段通过片段着色器 tile 图像读取,对深度/模板附件的读取访问权限。 -
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
指定通过深度或模板操作或某些渲染通道的加载和存储操作,对深度/模板附件的写入访问权限。这种访问发生在VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
或VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
管线阶段。 -
VK_ACCESS_TRANSFER_READ_BIT
指定在复制操作中对图像或缓冲区的读取访问权限。这种访问发生在VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT
管线阶段。 -
VK_ACCESS_TRANSFER_WRITE_BIT
指定在清除或复制操作中对图像或缓冲区的写入访问权限。这种访问发生在VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT
管线阶段。 -
VK_ACCESS_HOST_READ_BIT
指定主机操作的读取访问权限。此类型的访问不是通过资源执行的,而是直接在内存上执行的。这种访问发生在VK_PIPELINE_STAGE_HOST_BIT
管线阶段。 -
VK_ACCESS_HOST_WRITE_BIT
指定主机操作的写入访问权限。此类型的访问不是通过资源执行的,而是直接在内存上执行的。这种访问发生在VK_PIPELINE_STAGE_HOST_BIT
管线阶段。 -
VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT
指定作为条件渲染一部分的谓词的读取访问权限。这种访问发生在VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT
管线阶段。 -
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
指定当变换反馈处于活动状态时对变换反馈缓冲区的写入访问权限。这种访问发生在VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
管线阶段。 -
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
指定当vkCmdBeginTransformFeedbackEXT
执行时读取的变换反馈计数器缓冲区的读取访问权限。这种访问发生在VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
管线阶段。 -
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT
指定当vkCmdEndTransformFeedbackEXT
执行时写入的变换反馈计数器缓冲区的写入访问权限。这种访问发生在VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
管线阶段。 -
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV
指定从 vkCmdPreprocessGeneratedCommandsNV 的缓冲区输入读取数据。这种访问发生在VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV
管线阶段。 -
VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV
指定在 vkCmdPreprocessGeneratedCommandsNV 中写入目标命令缓冲区预处理输出。这种访问发生在VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV
管线阶段。 -
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT
指定从 vkCmdPreprocessGeneratedCommandsEXT 的缓冲区输入读取数据。这种访问发生在VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT
管线阶段。 -
VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT
指定在 vkCmdPreprocessGeneratedCommandsEXT 中写入目标命令缓冲区预处理输出。这种访问发生在VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT
管线阶段。 -
VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT
指定对颜色附件的读取访问权限,包括高级混合操作。这种访问发生在VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
管线阶段。 -
VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI
指定在VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI
管线阶段中对调用掩码图像的读取访问。 -
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR
指定在跟踪、构建或复制命令中对加速结构的读取访问权限,或者在构建命令中对加速结构暂存缓冲区的读取访问权限。这种访问发生在VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR
管线阶段或VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段。 -
VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR
指定在构建或复制命令中对加速结构或加速结构暂存缓冲区的写入访问权限。这种访问发生在VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段。 -
VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT
指定在动态片段密度图操作期间对片段密度图附件的读取访问权限。这种访问发生在VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
管线阶段。 -
VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR
指定在光栅化期间对片段着色率附件的读取访问权限。这种访问发生在VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
管线阶段。 -
VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV
指定在光栅化期间对着色率图像的读取访问权限。这种访问发生在VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV
管线阶段。它等同于VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
。
某些访问类型仅由流水线阶段的子集执行。任何同时使用阶段掩码和访问掩码的同步命令都使用两者来定义访问范围 - 只有由指定阶段执行的指定访问类型才包含在访问范围内。如果同步命令中不包含能够执行该类型访问的对应阶段掩码中的流水线阶段,则应用程序必须不指定访问标志。下表列出了每个访问标志,哪些流水线阶段可以执行该类型的访问。
访问标志 | 支持的流水线阶段 |
---|---|
|
任意 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
任意 |
|
任意 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Provided by VK_VERSION_1_0
typedef VkFlags VkAccessFlags;
VkAccessFlags
是一个位掩码类型,用于设置零个或多个 VkAccessFlagBits 的掩码。
如果内存对象不具有 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
属性,则必须调用 vkFlushMappedMemoryRanges,以保证主机对内存对象的写入对主机域可用,在那里它们可以通过域操作进一步对设备域可用。类似地,必须调用 vkInvalidateMappedMemoryRanges,以保证对主机域可用的写入对主机操作可见。
如果内存对象确实具有 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
属性标志,则主机对内存对象的写入会自动对主机域可用。类似地,对主机域可用的写入会自动对主机可见。
帧缓冲区区域依赖
在帧缓冲区上或相对于帧缓冲区操作的流水线阶段统称为帧缓冲区空间流水线阶段。这些阶段是
-
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
对于这些流水线阶段,从第一组操作到第二组操作的执行或内存依赖可以是单个帧缓冲区全局依赖,也可以拆分为多个帧缓冲区局部依赖。具有非帧缓冲区空间流水线阶段的依赖关系既不是帧缓冲区全局依赖,也不是帧缓冲区局部依赖。
帧缓冲区区域是整个帧缓冲区的子集,可以是
-
样本区域,这是一组样本(x、y、层、样本)坐标,是整个帧缓冲区的子集,或
-
片段区域,这是一组片段(x、y、层)坐标,是整个帧缓冲区的子集。
帧缓冲局部依赖的同步范围都只包括在相应帧缓冲区域内执行的操作(如下定义)。对于帧缓冲局部依赖,不保证不同帧缓冲区域之间的顺序。
帧缓冲全局依赖的同步范围包括对所有帧缓冲区域的操作。
如果第一个同步范围包括对具有 N 个样本的像素/片段的操作,而第二个同步范围包括对具有 M 个样本的像素/片段的操作,其中 N 不等于 M,则第一个同步范围中包含给定 (x, y, layer) 坐标处所有样本的帧缓冲区域对应于第二个同步范围中相同坐标处包含所有样本的区域。换句话说,帧缓冲区域是一个片段区域,它是一个像素粒度的依赖。如果 N 等于 M,并且 VkSubpassDescription
::flags
没有指定 VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM
标志,则第一个同步范围中包含单个 (x, y, layer, sample) 坐标的帧缓冲区域对应于第二个同步范围中相同坐标的相同样本的区域。换句话说,帧缓冲区域是一个样本区域,它是一个样本粒度的依赖。
如果执行操作的管线是使用 VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT
、VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT
或 VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT
创建的,则帧缓冲区域是一个片段区域,它是一个像素粒度的依赖。
由于片段着色器调用的运行没有指定任何特定的分组,因此帧缓冲区域的大小是实现相关的,应用程序不知道,并且必须假设不大于上述指定的大小。 |
实际上,像素与样本粒度依赖关系意味着,如果输入附件的样本数量与管线的 |
如果同步命令包含 dependencyFlags
参数,并指定了 VK_DEPENDENCY_BY_REGION_BIT
标志,则它为该同步命令中所有帧缓冲区域的帧缓冲空间管线阶段定义帧缓冲局部依赖。如果没有包含 dependencyFlags
参数,或者没有指定 VK_DEPENDENCY_BY_REGION_BIT
标志,则为这些阶段指定帧缓冲全局依赖。VK_DEPENDENCY_BY_REGION_BIT
标志不影响非帧缓冲空间管线阶段之间的依赖关系,也不影响帧缓冲空间和非帧缓冲空间管线阶段之间的依赖关系。
帧缓冲局部依赖对于大多数架构来说更有效率;特别是基于瓦片的架构 - 它可以将帧缓冲区域完全保存在片上寄存器中,从而避免跨此类依赖的外部带宽。在渲染中包含帧缓冲全局依赖通常会强制所有实现将数据刷新到内存或更高级别的缓存,从而破坏任何潜在的局部性优化。 |
视图局部依赖
在启用多视图的渲染通道实例中,依赖关系可以是视图局部的或视图全局的。
视图局部依赖仅包括来自第一个同步范围中源子通道的单个源视图的操作,并且仅包括来自第二个同步范围中目标子通道的单个目标视图的操作。视图全局依赖包括相应同步范围中源子通道和目标子通道的视图掩码中的所有视图。
如果同步命令包含 dependencyFlags
参数并指定了 VK_DEPENDENCY_VIEW_LOCAL_BIT
标志,则它为该同步命令的所有视图定义视图局部依赖。如果没有包含 dependencyFlags
参数,或者没有指定 VK_DEPENDENCY_VIEW_LOCAL_BIT
标志,则指定视图全局依赖。
设备局部依赖
依赖关系可以是设备局部的或非设备局部的。设备局部依赖充当多个单独的依赖关系,每个依赖关系对应一个执行同步命令的物理设备,其中每个依赖关系仅包括来自该物理设备在两个同步范围内的操作。非设备局部依赖是单个依赖,其中两个同步范围都包括来自参与同步命令的所有物理设备的操作。对于子通道依赖,VkDeviceGroupRenderPassBeginInfo::deviceMask
中的所有物理设备都参与依赖,对于管线屏障,命令缓冲区当前设备掩码中设置的所有物理设备都参与依赖。
如果同步命令包含 dependencyFlags
参数并指定了 VK_DEPENDENCY_DEVICE_GROUP_BIT
标志,则它为该同步命令定义非设备局部依赖。如果没有包含 dependencyFlags
参数,或者没有指定 VK_DEPENDENCY_DEVICE_GROUP_BIT
标志,则它为该同步命令定义设备局部依赖,适用于所有参与的物理设备。
信号量和事件依赖是设备局部的,并且只在执行依赖的一个物理设备上执行。
隐式同步保证
Vulkan 提供少量隐式排序保证,确保命令提交的顺序是有意义的,并避免常见操作中不必要的复杂性。
提交顺序是 Vulkan 中的基本排序,它使记录和提交到单个队列的操作和同步命令的顺序具有意义。Vulkan 中命令之间的显式和隐式排序保证都基于此排序是有意义的前提。此顺序本身不定义任何执行或内存依赖关系;同步命令和 API 内的其他排序使用此排序来定义其范围。
任何给定命令集的提交顺序取决于它们被记录到命令缓冲区然后被提交的顺序。 此顺序确定方式如下
-
初始顺序由主机上单个队列中 vkQueueSubmit 和 vkQueueSubmit2 命令的执行顺序(从先到后)决定。
-
VkSubmitInfo 结构在 vkQueueSubmit 的
pSubmits
参数中指定的顺序,或 VkSubmitInfo2 结构在 vkQueueSubmit2 的pSubmits
参数中指定的顺序,按索引从小到大排列。 -
命令缓冲区在 VkSubmitInfo 或 VkSubmitInfo2 的
pCommandBuffers
成员中指定的顺序,按索引从小到大排列。 -
在渲染通道之外的命令被记录到主机上的命令缓冲区的顺序,从先到后。
-
在单个子通道内,命令被记录到主机上的命令缓冲区的顺序,从先到后。
当使用具有多个子通道的渲染通道对象时,不同子通道中的命令彼此之间没有定义的提交顺序,无论子通道的记录顺序如何。子通道内的命令仍然相对于同一子通道内以及渲染通道之外的其他命令排序。 |
通过图形管线的图元顺序 和作为图像内存屏障一部分的图像布局转换 基于提交顺序提供额外的保证。
给定命令内管线阶段的执行也具有松散的顺序,仅取决于单个命令。
信号操作顺序是 Vulkan 中的一个基本顺序,它赋予在提交到单个队列时发生信号量和栅栏信号操作顺序的意义。 队列操作的信号操作顺序确定方式如下
-
初始顺序由主机上单个队列中 vkQueueSubmit 和 vkQueueSubmit2 命令的执行顺序(从先到后)决定。
-
VkSubmitInfo 结构在 vkQueueSubmit 的
pSubmits
参数中指定的顺序,或 VkSubmitInfo2 结构在 vkQueueSubmit2 的pSubmits
参数中指定的顺序,按索引从小到大排列。 -
vkQueueSubmit 或 vkQueueSubmit2 或 vkQueueBindSparse 命令的
fence
参数定义的栅栏信号操作在由该命令定义的所有信号量信号操作之后排序。
由单个 VkSubmitInfo 或 VkSubmitInfo2 或 VkBindSparseInfo 结构定义的信号量信号操作相对于在同一结构中定义的其他信号量信号操作是无序的。
vkSignalSemaphore 命令不在队列上执行,而是从主机执行信号操作。 执行 vkSignalSemaphore 命令定义的信号量信号操作在 vkSignalSemaphore 命令被调用之后发生,并在命令返回之前发生。
在信号时间线信号量时,应用程序有责任确保它们按严格递增的信号量值进行排序。 因为信号量信号操作的第一个同步范围包含所有在提交顺序中较早发生的信号量信号操作,因此保证任何给定批次中包含的所有信号量信号操作都发生在任何先前批次中包含的所有信号量信号操作之后。 但是,在单个批次中定义的信号量信号操作之间不提供排序保证。 这与时间线信号量值严格增加的要求相结合,意味着在单个批次中两次信号同一时间线信号量是无效的。 如果应用程序希望确保某些信号量信号操作在某些其他信号量信号操作之后发生,则可以提交一个单独的批次,其中仅包含信号量信号操作,这些操作将在任何较早批次中的信号量信号操作之后发生。 当从主机发送信号量信号时,唯一的排序保证是信号操作发生在调用vkSignalSemaphore之后,并在返回之前发生。 因此,如果队列提交的信号量上有任何未完成的信号操作,除非这些队列提交具有某些依赖关系,确保它们发生在主机信号操作之后,否则调用 |
栅栏
栅栏是一种同步原语,可以用于插入从队列到主机的依赖项。栅栏有两种状态 - 已发出信号和未发出信号。作为执行队列提交命令的一部分,栅栏可以发出信号。可以使用 vkResetFences 在主机上取消栅栏信号。可以使用 vkWaitForFences 命令由主机等待栅栏,并且可以使用vkGetFenceStatus查询当前状态。
栅栏的内部数据可能包含对与在该栅栏对象上执行的信号或取消信号操作相关的任何资源和待处理工作的引用,统称为栅栏的有效负载。提供了将内部数据导入和导出到栅栏的机制 下面。这些机制间接地使应用程序能够在进程和 API 边界上的两个或多个栅栏和其他同步原语之间共享栅栏状态。
栅栏由 VkFence
句柄表示
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence)
要创建栅栏,请调用
// Provided by VK_VERSION_1_0
VkResult vkCreateFence(
VkDevice device,
const VkFenceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence);
-
device
是创建栅栏的逻辑设备。 -
pCreateInfo
是指向 VkFenceCreateInfo 结构的指针,该结构包含有关如何创建栅栏的信息。 -
pAllocator
控制主机内存分配,具体描述请参考内存分配章节。 -
pFence
是一个指针,指向一个句柄,函数会将生成的栅栏对象返回到该句柄中。
VkFenceCreateInfo
结构定义如下:
// Provided by VK_VERSION_1_0
typedef struct VkFenceCreateInfo {
VkStructureType sType;
const void* pNext;
VkFenceCreateFlags flags;
} VkFenceCreateInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是一个 VkFenceCreateFlagBits 的位掩码,指定栅栏的初始状态和行为。
// Provided by VK_VERSION_1_0
typedef enum VkFenceCreateFlagBits {
VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
} VkFenceCreateFlagBits;
-
VK_FENCE_CREATE_SIGNALED_BIT
指定栅栏对象以已发出信号状态创建。否则,它以未发出信号状态创建。
// Provided by VK_VERSION_1_0
typedef VkFlags VkFenceCreateFlags;
VkFenceCreateFlags
是一个位掩码类型,用于设置零个或多个 VkFenceCreateFlagBits 的掩码。
要创建其负载可以导出到外部句柄的栅栏,请将 VkExportFenceCreateInfo 结构添加到 VkFenceCreateInfo 结构的 pNext
链中。VkExportFenceCreateInfo 结构的定义如下:
// Provided by VK_VERSION_1_1
typedef struct VkExportFenceCreateInfo {
VkStructureType sType;
const void* pNext;
VkExternalFenceHandleTypeFlags handleTypes;
} VkExportFenceCreateInfo;
或等效的
// Provided by VK_KHR_external_fence
typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
handleTypes
是 VkExternalFenceHandleTypeFlagBits 的位掩码,指定应用程序可以从生成的栅栏导出一个或多个栅栏句柄类型。应用程序可以为同一个栅栏请求多个句柄类型。
要指定从栅栏导出的 NT 句柄的其他属性,请将 VkExportFenceWin32HandleInfoKHR 结构添加到 VkFenceCreateInfo 结构的 pNext
链中。VkExportFenceWin32HandleInfoKHR 结构定义如下:
// Provided by VK_KHR_external_fence_win32
typedef struct VkExportFenceWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
const SECURITY_ATTRIBUTES* pAttributes;
DWORD dwAccess;
LPCWSTR name;
} VkExportFenceWin32HandleInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
pAttributes
是指向 WindowsSECURITY_ATTRIBUTES
结构的指针,指定句柄的安全属性。 -
dwAccess
是一个DWORD
,指定句柄的访问权限。 -
name
是一个以 null 结尾的 UTF-16 字符串,用于与从创建的栅栏导出的 NT 句柄引用的底层同步原语关联。
如果 VkExportFenceCreateInfo 不包含在同一个 pNext
链中,则忽略此结构。
如果在 VkFenceCreateInfo 的 pNext
链中包含 VkExportFenceCreateInfo 并带有 Windows handleType
,但 pNext
链中不包含 VkExportFenceWin32HandleInfoKHR
,或者包含但 pAttributes
为 NULL
,则将使用默认安全描述符值,并且应用程序创建的子进程将不会继承该句柄,如 MSDN 文档“Synchronization Object Security and Access Rights”1中所述。此外,如果该结构不存在,则访问权限将为
DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
对于以下类型的句柄
VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
要导出表示栅栏状态的 Windows 句柄,请调用
// Provided by VK_KHR_external_fence_win32
VkResult vkGetFenceWin32HandleKHR(
VkDevice device,
const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo,
HANDLE* pHandle);
-
device
是创建正在导出的栅栏的逻辑设备。 -
pGetWin32HandleInfo
是指向 VkFenceGetWin32HandleInfoKHR 结构的指针,该结构包含导出操作的参数。 -
pHandle
将返回表示栅栏状态的 Windows 句柄。
对于定义为 NT 句柄的句柄类型,vkGetFenceWin32HandleKHR
返回的句柄由应用程序所有。为了避免资源泄漏,应用程序在不再需要它们时必须使用 CloseHandle
系统调用释放它们的所有权。
从栅栏导出 Windows 句柄可能会产生副作用,具体取决于指定句柄类型的转移,如 导入栅栏负载中所述。
VkFenceGetWin32HandleInfoKHR
结构定义如下
// Provided by VK_KHR_external_fence_win32
typedef struct VkFenceGetWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkExternalFenceHandleTypeFlagBits handleType;
} VkFenceGetWin32HandleInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
fence
是将要导出状态的栅栏。 -
handleType
是一个 VkExternalFenceHandleTypeFlagBits 值,指定请求的句柄类型。
返回的句柄的属性取决于 handleType
的值。 有关定义的外部栅栏句柄类型的属性的描述,请参阅 VkExternalFenceHandleTypeFlagBits。
要导出表示栅栏负载的 POSIX 文件描述符,请调用
// Provided by VK_KHR_external_fence_fd
VkResult vkGetFenceFdKHR(
VkDevice device,
const VkFenceGetFdInfoKHR* pGetFdInfo,
int* pFd);
-
device
是创建正在导出的栅栏的逻辑设备。 -
pGetFdInfo
是一个指向 VkFenceGetFdInfoKHR 结构的指针,该结构包含导出操作的参数。 -
pFd
将返回表示栅栏负载的文件描述符。
每次调用 vkGetFenceFdKHR
必须创建一个新的文件描述符,并将所有权转移给应用程序。 为了避免资源泄漏,应用程序在不再需要文件描述符时必须释放文件描述符的所有权。
可以通过多种方式释放所有权。 例如,应用程序可以对文件描述符调用 |
如果 pGetFdInfo->handleType
是 VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
并且在调用 vkGetFenceFdKHR
时栅栏被触发,则 pFd
可以返回 -1
值而不是有效的文件描述符。
如果操作系统支持,则实现必须设置文件描述符在进行 execve
系统调用时自动关闭。
从栅栏导出文件描述符可能会产生副作用,具体取决于指定句柄类型的转移,如 导入栅栏状态中所述。
VkFenceGetFdInfoKHR
结构定义如下
// Provided by VK_KHR_external_fence_fd
typedef struct VkFenceGetFdInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkExternalFenceHandleTypeFlagBits handleType;
} VkFenceGetFdInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
fence
是将要导出状态的栅栏。 -
handleType
是一个 VkExternalFenceHandleTypeFlagBits 值,指定请求的句柄类型。
返回的文件描述符的属性取决于 handleType
的值。 有关定义的外部栅栏句柄类型的属性的描述,请参阅 VkExternalFenceHandleTypeFlagBits。
要销毁一个栅栏,调用
// Provided by VK_VERSION_1_0
void vkDestroyFence(
VkDevice device,
VkFence fence,
const VkAllocationCallbacks* pAllocator);
-
device
是销毁栅栏的逻辑设备。 -
fence
是要销毁的栅栏的句柄。 -
pAllocator
控制主机内存分配,具体描述请参考内存分配章节。
要从主机查询栅栏的状态,调用
// Provided by VK_VERSION_1_0
VkResult vkGetFenceStatus(
VkDevice device,
VkFence fence);
-
device
是拥有栅栏的逻辑设备。 -
fence
是要查询的栅栏的句柄。
成功后,vkGetFenceStatus
返回栅栏对象的状态,并具有以下返回代码
状态 | 含义 |
---|---|
|
|
|
|
|
设备已丢失。请参阅丢失的设备。 |
如果队列提交命令正在等待执行,则此命令返回的值可能会立即过时。
如果设备已丢失(请参阅丢失的设备),vkGetFenceStatus
可能会返回上述任何状态代码。如果设备已丢失并且重复调用 vkGetFenceStatus
,它最终将返回 VK_SUCCESS
或 VK_ERROR_DEVICE_LOST
。
要从主机将栅栏的状态设置为未发出信号,调用
// Provided by VK_VERSION_1_0
VkResult vkResetFences(
VkDevice device,
uint32_t fenceCount,
const VkFence* pFences);
-
device
是拥有栅栏的逻辑设备。 -
fenceCount
是要重置的栅栏的数量。 -
pFences
是指向要重置的栅栏句柄数组的指针。
如果 pFences
的任何成员当前已将其有效负载导入为临时持久性,则首先恢复该栅栏的先前永久有效负载。因此,其余描述的操作在恢复的有效负载上进行操作。
当在主机上执行 vkResetFences 时,它为每个栅栏定义一个栅栏未发出信号操作,该操作将栅栏重置为未发出信号的状态。
如果当执行 vkResetFences 时,pFences
的任何成员已处于未发出信号的状态,则 vkResetFences 对该栅栏无效。
当一个栅栏作为队列提交命令的一部分提交到队列时,它定义了对作为该命令一部分提交的批次的内存依赖性,并定义了栅栏发出信号操作,该操作将栅栏设置为已发出信号的状态。
第一个同步范围包括在同一个队列提交命令中提交的每个批次。由 vkQueueSubmit 或 vkQueueSubmit2 定义的栅栏发出信号操作还包括在第一个同步范围内的所有在提交顺序中较早发生的命令。由 vkQueueSubmit 或 vkQueueSubmit2 或 vkQueueBindSparse 定义的栅栏发出信号操作还包括在第一个同步范围内的任何在信号操作顺序中较早发生的信号量和栅栏发出信号操作。
第二个同步范围仅包括栅栏发出信号操作。
第一个访问范围包括设备执行的所有内存访问。
第二个访问范围为空。
要在主机上等待一个或多个栅栏进入已发出信号的状态,调用
// Provided by VK_VERSION_1_0
VkResult vkWaitForFences(
VkDevice device,
uint32_t fenceCount,
const VkFence* pFences,
VkBool32 waitAll,
uint64_t timeout);
-
device
是拥有栅栏的逻辑设备。 -
fenceCount
是要等待的栅栏的数量。 -
pFences
是指向fenceCount
个栅栏句柄的数组的指针。 -
waitAll
是要成功解除阻塞等待必须满足的条件。如果waitAll
为VK_TRUE
,则条件是pFences
中的所有栅栏都已发出信号。否则,条件是pFences
中至少有一个栅栏已发出信号。 -
timeout
是以纳秒为单位的超时时间。timeout
会调整为实现定义的超时精度所允许的最接近的值,该值可能比一纳秒长得多,并且可能比请求的时间长。
如果在调用 vkWaitForFences
时满足条件,则 vkWaitForFences
会立即返回。如果在调用 vkWaitForFences
时未满足条件,则 vkWaitForFences
将会阻塞并等待,直到条件满足或 timeout
过期,以较早者为准。
如果 timeout
为零,则 vkWaitForFences
不会等待,而只是返回栅栏的当前状态。如果未满足条件,即使没有执行实际等待,在这种情况下也会返回 VK_TIMEOUT
。
如果在 timeout
过期之前满足条件,则 vkWaitForFences
返回 VK_SUCCESS
。否则,vkWaitForFences
在 timeout
过期后返回 VK_TIMEOUT
。
如果设备丢失(参见设备丢失)发生在超时时间到期之前,vkWaitForFences
必须在有限的时间内返回,返回值为 VK_SUCCESS
或 VK_ERROR_DEVICE_LOST
。
虽然我们保证 |
执行依赖性是通过等待栅栏变为已发出信号状态来定义的,可以通过 vkWaitForFences 或轮询 vkGetFenceStatus 来实现。
第一个同步范围仅包括栅栏信号操作。
第二个同步范围包括主机操作 vkWaitForFences 或 vkGetFenceStatus,它们指示栅栏已变为已发出信号状态。
发出栅栏信号的替代方法
除了将栅栏作为队列提交命令的一部分提交到队列之外,当设备或显示器上发生特定事件时,可以发出栅栏信号。
要创建一个当设备上发生事件时将发出信号的栅栏,请调用
// Provided by VK_EXT_display_control
VkResult vkRegisterDeviceEventEXT(
VkDevice device,
const VkDeviceEventInfoEXT* pDeviceEventInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence);
-
device
是一个逻辑设备,事件可能在该设备上发生。 -
pDeviceEventInfo
是一个指向 VkDeviceEventInfoEXT 结构的指针,该结构描述了应用程序感兴趣的事件。 -
pAllocator
控制主机内存分配,具体描述请参考内存分配章节。 -
pFence
是一个指针,指向一个句柄,函数会将生成的栅栏对象返回到该句柄中。
VkDeviceEventInfoEXT
结构定义如下
// Provided by VK_EXT_display_control
typedef struct VkDeviceEventInfoEXT {
VkStructureType sType;
const void* pNext;
VkDeviceEventTypeEXT deviceEvent;
} VkDeviceEventInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
device
是一个 VkDeviceEventTypeEXT 值,指定何时发出栅栏信号。
VkDeviceEventInfoEXT::device
的可能值,指定何时发出栅栏信号,如下所示
// Provided by VK_EXT_display_control
typedef enum VkDeviceEventTypeEXT {
VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0,
} VkDeviceEventTypeEXT;
-
VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT
指定当显示器插入或拔出指定设备时发出栅栏信号。应用程序可以使用此通知来确定何时需要重新枚举设备上可用的显示器。
要创建一个当 VkDisplayKHR 对象上发生事件时将发出信号的栅栏,请调用
// Provided by VK_EXT_display_control
VkResult vkRegisterDisplayEventEXT(
VkDevice device,
VkDisplayKHR display,
const VkDisplayEventInfoEXT* pDisplayEventInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence);
-
device
是与display
关联的逻辑设备 -
display
是事件可能发生的显示器。 -
pDisplayEventInfo
是一个指向 VkDisplayEventInfoEXT 结构的指针,该结构描述了应用程序感兴趣的事件。 -
pAllocator
控制主机内存分配,具体描述请参考内存分配章节。 -
pFence
是一个指针,指向一个句柄,函数会将生成的栅栏对象返回到该句柄中。
VkDisplayEventInfoEXT
结构定义如下
// Provided by VK_EXT_display_control
typedef struct VkDisplayEventInfoEXT {
VkStructureType sType;
const void* pNext;
VkDisplayEventTypeEXT displayEvent;
} VkDisplayEventInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
displayEvent
是一个 VkDisplayEventTypeEXT,指定何时发出栅栏信号。
VkDisplayEventInfoEXT::displayEvent
的可能值,指定何时发出栅栏信号,如下所示
// Provided by VK_EXT_display_control
typedef enum VkDisplayEventTypeEXT {
VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0,
} VkDisplayEventTypeEXT;
-
VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT
指定当下一个显示刷新周期的第一个像素离开显示引擎到达显示器时发出栅栏信号。
导入栅栏负载
应用程序可以使用外部栅栏句柄将栅栏负载导入到现有的栅栏中。导入操作的效果将是临时的或永久的,具体取决于应用程序的指定。如果导入是临时的,则下次将栅栏传递给 vkResetFences 时,栅栏将恢复到其永久状态。
将栅栏恢复到其之前的永久负载与重置栅栏负载是不同的操作。有关更多详细信息,请参见 vkResetFences。 |
在重置栅栏之前对栅栏执行后续的临时导入不会对此要求产生任何影响;栅栏的下一个未发出信号状态必须仍然恢复其最后一个永久状态。永久负载导入的行为就像目标栅栏被销毁,并且创建了一个具有相同句柄但导入了负载的新栅栏。由于临时或永久导入栅栏负载会将现有负载从栅栏中分离,因此任何导入栅栏负载的命令都适用与 vkDestroyFence
类似的用法限制。使用哪种导入类型称为导入操作的持久性。每种句柄类型都支持一种或两种类型的持久性。
实现必须根据指定的外部栅栏句柄的类型,通过引用或复制该句柄所引用的负载来执行导入操作。所使用的导入方法称为句柄类型的转移。当使用具有引用转移的句柄类型时,将负载导入栅栏会将该栅栏添加到共享该负载的所有栅栏的集合中。此集合包括从中导出负载的栅栏。对集合中的任何栅栏执行的栅栏信号发送、等待和重置操作必须表现得好像该集合是一个单独的栅栏。使用具有复制转移的句柄类型导入负载会在导入时创建负载的重复副本,但不再引用它。对复制导入的目标执行的栅栏信号发送、等待和重置操作必须不影响任何其他栅栏或负载。
导出操作具有与指定句柄类型的导入操作相同的转移方式。此外,将栅栏负载导出到具有复制转移的句柄会对源栅栏的负载产生与执行栅栏重置操作相同的副作用。如果栅栏使用的是临时导入的负载,则该栅栏之前的永久负载将被恢复。
表 |
外部同步允许实现修改对象的内部状态,即负载,而无需内部同步。然而,对于跨进程共享负载的栅栏,满足 VkFence
参数的外部同步要求(就好像集合中的所有栅栏都是同一个对象)有时是不可行的。同样,满足栅栏状态的有效使用约束将需要进程之间不切实际的协调或信任级别。因此,这些约束仅适用于特定的栅栏句柄,而不适用于其负载。对于共享负载的不同栅栏对象
-
如果同时调用多个排队信号操作或取消信号栅栏的命令,行为将如同这些命令以任意顺序依次调用。
-
如果使用正在共享负载的栅栏调用队列提交命令,并且该负载已与另一个尚未完成执行的队列命令关联,则其中一个或两个命令将在完成执行时导致栅栏变为已信号状态。
-
如果栅栏负载在与尚未完成执行的队列命令关联时被重置,则该负载将变为未信号状态,但可能在命令完成执行时再次变为已信号状态。
-
在上述情况下,与共享负载的栅栏关联的任何设备可能会丢失,或者任何队列提交或栅栏重置命令可能会返回
VK_ERROR_INITIALIZATION_FAILED
。
除了这些不确定的结果外,行为是明确定义的。特别是
-
实现必须不崩溃或进入内部不一致的状态,在这种状态下,未来有效的 Vulkan 命令可能会导致未定义的结果,
-
未来对共享负载的栅栏的等待命令的超时必须有效。
这些规则允许进程同步对共享内存的访问,而无需相互信任。然而,这些进程仍然必须小心,不要将共享栅栏用于除同步对共享内存的访问之外的用途。例如,一个进程不应使用具有共享负载的栅栏来判断其提交到队列的命令何时完成,以及这些命令使用的对象何时可以被销毁,因为另一个进程可能会意外或恶意地导致栅栏在命令实际完成之前发出信号。 |
当栅栏使用导入的负载时,它的VkExportFenceCreateInfo::handleTypes
值是在创建从中导出负载的栅栏时指定的,而不是在创建栅栏时指定的。此外,VkExternalFenceProperties::exportFromImportedHandleTypes
会根据用于导入当前负载的特定句柄类型,限制可以从此类栅栏导出的句柄类型。将栅栏传递给vkAcquireNextImageKHR等同于将栅栏负载临时导入该栅栏。
由于导入的栅栏的可导出句柄类型与其当前导入的负载相对应,并且vkAcquireNextImageKHR的行为与临时导入操作相同,其中源栅栏对应用程序是不透明的,因此应用程序无法确定是否可以从处于此状态的栅栏导出任何外部句柄类型。因此,应用程序必须不要尝试从使用来自vkAcquireNextImageKHR的临时导入负载的栅栏导出句柄。 |
当导入栅栏负载时,应用程序有责任确保外部句柄满足所有有效的使用要求。然而,实现必须对外部句柄执行充分的验证,以确保该操作产生有效的栅栏,该栅栏在按照其导入参数允许使用时,不会导致程序终止、设备丢失、队列停滞、主机线程停滞或损坏其他资源。如果提供的外部句柄不满足这些要求,实现必须使用错误代码 VK_ERROR_INVALID_EXTERNAL_HANDLE
使栅栏负载导入操作失败。
要从 Windows 句柄导入栅栏负载,请调用
// Provided by VK_KHR_external_fence_win32
VkResult vkImportFenceWin32HandleKHR(
VkDevice device,
const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
-
device
是创建栅栏的逻辑设备。 -
pImportFenceWin32HandleInfo
是指向 VkImportFenceWin32HandleInfoKHR 结构的指针,该结构指定栅栏和导入参数。
从 Windows 句柄导入栅栏负载不会将句柄的所有权转移给 Vulkan 实现。对于定义为 NT 句柄的句柄类型,当不再需要该句柄时,应用程序必须使用 CloseHandle
系统调用释放所有权。
应用程序可以将相同的栅栏负载导入到 Vulkan 的多个实例中,导入到从中导出它的同一实例中,以及多次导入到给定的 Vulkan 实例中。
VkImportFenceWin32HandleInfoKHR
结构定义为
// Provided by VK_KHR_external_fence_win32
typedef struct VkImportFenceWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkFenceImportFlags flags;
VkExternalFenceHandleTypeFlagBits handleType;
HANDLE handle;
LPCWSTR name;
} VkImportFenceWin32HandleInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
fence
是将状态导入其中的栅栏。 -
flags
是 VkFenceImportFlagBits 的位掩码,指定栅栏负载导入操作的其他参数。 -
handleType
是一个 VkExternalFenceHandleTypeFlagBits 值,指定handle
的类型。 -
handle
是NULL
或要导入的外部句柄。 -
name
是NULL
或一个以 null 结尾的 UTF-16 字符串,命名要导入的底层同步原语。
handleType
支持的句柄类型为
句柄类型 | 转移方式 | 支持的持久性 |
---|---|---|
|
参考 |
临时,永久 |
|
参考 |
临时,永久 |
要从 POSIX 文件描述符导入栅栏有效负载,请调用
// Provided by VK_KHR_external_fence_fd
VkResult vkImportFenceFdKHR(
VkDevice device,
const VkImportFenceFdInfoKHR* pImportFenceFdInfo);
-
device
是创建栅栏的逻辑设备。 -
pImportFenceFdInfo
是指向 VkImportFenceFdInfoKHR 结构的指针,该结构指定栅栏和导入参数。
从文件描述符导入栅栏有效负载会将文件描述符的所有权从应用程序转移到 Vulkan 实现。在成功导入后,应用程序必须不对文件描述符执行任何操作。
应用程序可以将相同的栅栏负载导入到 Vulkan 的多个实例中,导入到从中导出它的同一实例中,以及多次导入到给定的 Vulkan 实例中。
VkImportFenceFdInfoKHR
结构定义如下
// Provided by VK_KHR_external_fence_fd
typedef struct VkImportFenceFdInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkFenceImportFlags flags;
VkExternalFenceHandleTypeFlagBits handleType;
int fd;
} VkImportFenceFdInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
fence
是将导入有效负载的栅栏。 -
flags
是 VkFenceImportFlagBits 的位掩码,指定栅栏负载导入操作的其他参数。 -
handleType
是一个 VkExternalFenceHandleTypeFlagBits 值,指定fd
的类型。 -
fd
是要导入的外部句柄。
handleType
支持的句柄类型为
句柄类型 | 转移方式 | 支持的持久性 |
---|---|---|
|
参考 |
临时,永久 |
|
复制 |
临时 |
如果 handleType
是 VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
,则 fd
的特殊值 -1
被视为指向已发出信号的对象的有效同步文件描述符。导入操作将成功,并且 VkFence
将具有临时导入的有效负载,就像提供了有效的文件描述符一样。
导入无效的同步文件描述符的这种特殊行为允许更容易地与其他系统 API 互操作,这些系统 API 使用无效的同步文件描述符表示已完成且不需要等待的工作的约定。这与实现从已发出信号的 |
可在以下项中设置的位
-
VkImportFenceFdInfoKHR::
flags
指定栅栏导入操作的其他参数是
// Provided by VK_VERSION_1_1
typedef enum VkFenceImportFlagBits {
VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001,
// Provided by VK_KHR_external_fence
VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = VK_FENCE_IMPORT_TEMPORARY_BIT,
} VkFenceImportFlagBits;
或等效的
// Provided by VK_KHR_external_fence
typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR;
-
VK_FENCE_IMPORT_TEMPORARY_BIT
指定栅栏有效负载将仅临时导入,如导入栅栏有效负载中所述,而与handleType
的持久性无关。
// Provided by VK_VERSION_1_1
typedef VkFlags VkFenceImportFlags;
或等效的
// Provided by VK_KHR_external_fence
typedef VkFenceImportFlags VkFenceImportFlagsKHR;
VkFenceImportFlags
是一种位掩码类型,用于设置零个或多个 VkFenceImportFlagBits 的掩码。
信号量
信号量是一种同步原语,可以用于在队列操作之间或队列操作与主机之间插入依赖关系。 二元信号量有两种状态 - 已触发和未触发。时间线信号量有一个严格递增的 64 位无符号整数有效负载,并根据特定的参考值触发。 队列操作执行完成后,可以触发信号量,队列操作可以等待信号量被触发后才开始执行。此外,时间线信号量可以通过主机使用 vkSignalSemaphore 命令触发,并使用 vkWaitSemaphores 命令从主机等待。
信号量的内部数据可能包括对与在该信号量对象上执行的触发或未触发操作相关的任何资源和待处理工作的引用,这些统称为信号量的有效负载。下面提供了将该内部数据导入和导出到信号量的机制。这些机制间接地使应用程序能够在两个或多个信号量以及跨进程和 API 边界的其他同步原语之间共享信号量状态。
信号量由 VkSemaphore
句柄表示
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore)
要创建信号量,请调用
// Provided by VK_VERSION_1_0
VkResult vkCreateSemaphore(
VkDevice device,
const VkSemaphoreCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSemaphore* pSemaphore);
-
device
是创建信号量的逻辑设备。 -
pCreateInfo
是指向 VkSemaphoreCreateInfo 结构的指针,该结构包含有关如何创建信号量的信息。 -
pAllocator
控制主机内存分配,具体描述请参考内存分配章节。 -
pSemaphore
是指向句柄的指针,其中返回生成的信号量对象。
VkSemaphoreCreateInfo
结构定义如下
// Provided by VK_VERSION_1_0
typedef struct VkSemaphoreCreateInfo {
VkStructureType sType;
const void* pNext;
VkSemaphoreCreateFlags flags;
} VkSemaphoreCreateInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
保留供将来使用。
// Provided by VK_VERSION_1_0
typedef VkFlags VkSemaphoreCreateFlags;
VkSemaphoreCreateFlags
是用于设置掩码的位掩码类型,但目前保留供将来使用。
VkSemaphoreTypeCreateInfo
结构定义如下
// Provided by VK_VERSION_1_2
typedef struct VkSemaphoreTypeCreateInfo {
VkStructureType sType;
const void* pNext;
VkSemaphoreType semaphoreType;
uint64_t initialValue;
} VkSemaphoreTypeCreateInfo;
或等效的
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreTypeCreateInfo VkSemaphoreTypeCreateInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphoreType
是一个 VkSemaphoreType 值,用于指定信号量的类型。 -
如果
semaphoreType
为VK_SEMAPHORE_TYPE_TIMELINE
,则initialValue
为初始有效负载值。
要创建特定类型的信号量,请将 VkSemaphoreTypeCreateInfo
结构添加到 VkSemaphoreCreateInfo::pNext
链。
如果 VkSemaphoreCreateInfo 的 pNext
链中未包含 VkSemaphoreTypeCreateInfo
结构,则创建的信号量将具有默认的 VkSemaphoreType VK_SEMAPHORE_TYPE_BINARY
。
以下是 VkSemaphoreTypeCreateInfo::semaphoreType
的可能值,用于指定信号量的类型:
// Provided by VK_VERSION_1_2
typedef enum VkSemaphoreType {
VK_SEMAPHORE_TYPE_BINARY = 0,
VK_SEMAPHORE_TYPE_TIMELINE = 1,
// Provided by VK_KHR_timeline_semaphore
VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY,
// Provided by VK_KHR_timeline_semaphore
VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE,
} VkSemaphoreType;
或等效的
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreType VkSemaphoreTypeKHR;
-
VK_SEMAPHORE_TYPE_BINARY
指定二元信号量类型,该类型具有一个布尔有效负载,指示信号量当前是已触发还是未触发。创建时,信号量处于未触发状态。 -
VK_SEMAPHORE_TYPE_TIMELINE
指定时间线信号量类型,该类型具有严格递增的 64 位无符号整数有效负载,指示信号量是否相对于特定的参考值触发。创建时,信号量有效负载的值由 VkSemaphoreTypeCreateInfo 的initialValue
字段给出。
要创建一个可以将其有效负载导出到外部句柄的信号量,请将 VkExportSemaphoreCreateInfo 结构添加到 VkSemaphoreCreateInfo 结构的 pNext
链。VkExportSemaphoreCreateInfo
结构定义如下
// Provided by VK_VERSION_1_1
typedef struct VkExportSemaphoreCreateInfo {
VkStructureType sType;
const void* pNext;
VkExternalSemaphoreHandleTypeFlags handleTypes;
} VkExportSemaphoreCreateInfo;
或等效的
// Provided by VK_KHR_external_semaphore
typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
handleTypes
是 VkExternalSemaphoreHandleTypeFlagBits 的位掩码,指定应用程序可以从生成的信号量导出的一个或多个信号量句柄类型。应用程序可以为同一个信号量请求多个句柄类型。
要指定从信号量导出的 NT 句柄的附加属性,请将 VkExportSemaphoreWin32HandleInfoKHR
结构添加到 VkSemaphoreCreateInfo 结构的 pNext
链。VkExportSemaphoreWin32HandleInfoKHR
结构定义如下
// Provided by VK_KHR_external_semaphore_win32
typedef struct VkExportSemaphoreWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
const SECURITY_ATTRIBUTES* pAttributes;
DWORD dwAccess;
LPCWSTR name;
} VkExportSemaphoreWin32HandleInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
pAttributes
是指向 WindowsSECURITY_ATTRIBUTES
结构的指针,指定句柄的安全属性。 -
dwAccess
是一个DWORD
,指定句柄的访问权限。 -
name
是一个以 null 结尾的 UTF-16 字符串,用于与从创建的信号量导出的 NT 句柄引用的底层同步原语关联。
如果 VkExportSemaphoreCreateInfo 未包含在同一个 pNext
链中,则忽略此结构。
如果 VkExportSemaphoreCreateInfo 包含在带有 Windows handleType
的 VkSemaphoreCreateInfo 的 pNext
链中,但 VkExportSemaphoreWin32HandleInfoKHR
未包含在 pNext
链中,或者它被包含但 pAttributes
为 NULL
,则将使用默认的安全描述符值,并且应用程序创建的子进程将不会继承该句柄,如 MSDN 文档“同步对象安全和访问权限”1 中所述。此外,如果该结构不存在,则使用的访问权限取决于句柄类型。
对于以下类型的句柄
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
实现必须确保访问权限允许对信号量执行信号和等待操作。
对于以下类型的句柄
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT
访问权限必须为
GENERIC_ALL
要导出表示信号量有效负载的 Windows 句柄,请调用
// Provided by VK_KHR_external_semaphore_win32
VkResult vkGetSemaphoreWin32HandleKHR(
VkDevice device,
const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo,
HANDLE* pHandle);
-
device
是创建要导出的信号量的逻辑设备。 -
pGetWin32HandleInfo
是指向 VkSemaphoreGetWin32HandleInfoKHR 结构的指针,该结构包含导出操作的参数。 -
pHandle
将返回表示信号量状态的 Windows 句柄。
对于定义为 NT 句柄的句柄类型,vkGetSemaphoreWin32HandleKHR
返回的句柄归应用程序所有。为了避免资源泄漏,当不再需要这些句柄时,应用程序必须使用 CloseHandle
系统调用释放它们的所有权。
从信号量导出 Windows 句柄可能具有副作用,具体取决于指定句柄类型的转移,如导入信号量有效负载中所述。
VkSemaphoreGetWin32HandleInfoKHR
结构定义如下
// Provided by VK_KHR_external_semaphore_win32
typedef struct VkSemaphoreGetWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetWin32HandleInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphore
是要从中导出状态的信号量。 -
handleType
是一个 VkExternalSemaphoreHandleTypeFlagBits 值,指定请求的句柄类型。
返回的句柄的属性取决于 handleType
的值。有关定义的外部信号量句柄类型的属性描述,请参阅 VkExternalSemaphoreHandleTypeFlagBits。
VkQueryLowLatencySupportNV
结构定义如下
// Provided by VK_NV_low_latency
typedef struct VkQueryLowLatencySupportNV {
VkStructureType sType;
const void* pNext;
void* pQueriedLowLatencyData;
} VkQueryLowLatencySupportNV;
此结构描述以下功能
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
pQueriedLowLatencyData
用于 NVIDIA Reflex 支持。
要导出表示信号量有效负载的 POSIX 文件描述符,请调用
// Provided by VK_KHR_external_semaphore_fd
VkResult vkGetSemaphoreFdKHR(
VkDevice device,
const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
int* pFd);
-
device
是创建要导出的信号量的逻辑设备。 -
pGetFdInfo
是指向 VkSemaphoreGetFdInfoKHR 结构的指针,该结构包含导出操作的参数。 -
pFd
将返回表示信号量负载的文件描述符。
每次调用 vkGetSemaphoreFdKHR
**必须** 创建一个新的文件描述符,并将所有权转移给应用程序。为了避免资源泄漏,应用程序在不再需要文件描述符时**必须**释放其所有权。
所有权可以通过多种方式释放。例如,应用程序可以对文件描述符调用 |
如果操作系统支持,则实现必须设置文件描述符在进行 execve
系统调用时自动关闭。
从信号量导出文件描述符**可能**会产生副作用,具体取决于指定句柄类型的转移,如 导入信号量状态 中所述。
VkSemaphoreGetFdInfoKHR
结构定义如下:
// Provided by VK_KHR_external_semaphore_fd
typedef struct VkSemaphoreGetFdInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetFdInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphore
是要从中导出状态的信号量。 -
handleType
是一个 VkExternalSemaphoreHandleTypeFlagBits 值,指定请求的句柄类型。
返回的文件描述符的属性取决于 handleType
的值。有关定义的外部信号量句柄类型的属性的描述,请参阅 VkExternalSemaphoreHandleTypeFlagBits。
要导出表示信号量负载的 Zircon 事件句柄,请调用
// Provided by VK_FUCHSIA_external_semaphore
VkResult vkGetSemaphoreZirconHandleFUCHSIA(
VkDevice device,
const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo,
zx_handle_t* pZirconHandle);
-
device
是创建要导出的信号量的逻辑设备。 -
pGetZirconHandleInfo
是指向 VkSemaphoreGetZirconHandleInfoFUCHSIA 结构的指针,该结构包含导出操作的参数。 -
pZirconHandle
将返回表示信号量负载的 Zircon 事件句柄。
每次调用 vkGetSemaphoreZirconHandleFUCHSIA
**必须** 创建一个 Zircon 事件句柄,并将所有权转移给应用程序。为了避免资源泄漏,应用程序在不再需要 Zircon 事件句柄时**必须**释放其所有权。
所有权可以通过多种方式释放。例如,应用程序可以对文件描述符调用 zx_handle_close(),或者通过使用文件描述符导入信号量负载将所有权转移回 Vulkan。 |
从信号量导出 Zircon 事件句柄**可能**会产生副作用,具体取决于指定句柄类型的转移,如 导入信号量状态 中所述。
VkSemaphoreGetZirconHandleInfoFUCHSIA
结构定义如下:
// Provided by VK_FUCHSIA_external_semaphore
typedef struct VkSemaphoreGetZirconHandleInfoFUCHSIA {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetZirconHandleInfoFUCHSIA;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphore
是要从中导出状态的信号量。 -
handleType
是一个 VkExternalSemaphoreHandleTypeFlagBits 值,指定请求的句柄类型。
返回的 Zircon 事件句柄的属性取决于 handleType
的值。有关定义的外部信号量句柄类型的属性的描述,请参阅 VkExternalSemaphoreHandleTypeFlagBits。
要销毁信号量,请调用
// Provided by VK_VERSION_1_0
void vkDestroySemaphore(
VkDevice device,
VkSemaphore semaphore,
const VkAllocationCallbacks* pAllocator);
-
device
是销毁信号量的逻辑设备。 -
semaphore
是要销毁的信号量的句柄。 -
pAllocator
控制主机内存分配,具体描述请参考内存分配章节。
信号量发出信号
当通过 队列提交 将批次提交到队列时,如果它包含要发出信号的信号量,则它定义了对该批次的内存依赖关系,并定义了将信号量设置为已发出信号状态的信号量发出信号操作。
如果信号量是使用 VK_SEMAPHORE_TYPE_TIMELINE
的 VkSemaphoreType 创建的,则该信号量被认为相对于在 VkTimelineSemaphoreSubmitInfo 或 VkSemaphoreSignalInfo 中指定的要发出信号的计数器值而发出信号。
第一个 同步范围 包括在同一批次中提交的每个命令。对于 vkQueueSubmit2,第一个同步范围被限制为 VkSemaphoreSubmitInfo::stageMask
指定的管线阶段。由 vkQueueSubmit 或 vkQueueSubmit2 定义的信号量发出信号操作还包括在 提交顺序 中较早发生的所有命令。由 vkQueueSubmit 或 vkQueueSubmit2 或 vkQueueBindSparse 定义的信号量发出信号操作还在第一个同步范围中包括在 信号操作顺序 中较早发生的任何信号量和栅栏发出信号操作。
第二个 同步范围 仅包括信号量发出信号操作。
第一个访问范围包括设备执行的所有内存访问。
第二个访问范围为空。
信号量等待
当通过 队列提交 将批次提交到队列时,如果它包含要等待的信号量,则它定义了先前的信号量发出信号操作与该批次之间的内存依赖关系,并定义了信号量等待操作。
此类信号量等待操作将使用 VK_SEMAPHORE_TYPE_BINARY
的 VkSemaphoreType 创建的信号量设置为未发出信号状态。如果信号量是使用 VK_SEMAPHORE_TYPE_TIMELINE
的 VkSemaphoreType 创建的,则如果信号量发出信号的值大于或等于信号量等待的值,则先前的信号量发出信号操作将定义与信号量等待操作的内存依赖关系,因此,该信号量将继续被认为相对于在 VkTimelineSemaphoreSubmitInfo 中指定的等待计数器值而发出信号。
-
对于二进制信号量,发出信号操作要么在同一队列上的 提交顺序 中较早发生,要么由主机操作发生在主机上提交此批次之前的命令提交
-
对于二进制信号量,不存在发生在发出信号操作之后和此等待操作之前的等待操作
-
不保证发出信号操作在此批次的信号量等待操作之后发生
-
对于时间线信号量,发出信号的值大于或等于等待值
如果多个信号量发出信号操作满足这些条件,则可以包括这些操作中的任何一个作为第一个 同步范围。在等待二进制信号量时,应用程序必须确保只有一个信号量发出信号操作满足这些条件。
第二个 同步范围 包括在同一批次中提交的每个命令。对于 vkQueueSubmit,第二个同步范围被限制为由 pWaitDstStageMask
的相应元素指定的目标阶段掩码确定的管线阶段上的操作。对于 vkQueueSubmit2,第二个同步范围被限制为 VkSemaphoreSubmitInfo::stageMask
指定的管线阶段。此外,无论是 vkQueueSubmit2 还是 vkQueueSubmit,第二个同步范围还包括在 提交顺序 中较晚发生的所有命令。
第一个 访问范围 为空。
第二个 访问范围 包括设备执行的所有内存访问。
信号量等待操作发生在执行依赖关系中的第一组操作之后,并且发生在执行依赖关系中的第二组操作之前。
与时间线信号量、栅栏或事件不同,等待二进制信号量也会在等待完成后取消该信号量的信号。应用程序必须确保在两个此类等待操作之间,该信号量再次发出信号,并使用执行依赖关系来确保这些操作按顺序发生。因此,二进制信号量等待和发出信号应成对离散地发生。 |
将 如果在可演示图像在帧缓冲区中使用之前需要对其执行图像布局转换,则该转换可以作为获取图像后提交到队列的第一个操作执行,并且不应阻止其他工作与演示操作重叠。例如,
或者,如果不需要保留图像的内容,则 此屏障在之前的呈现操作和后续的颜色附件输出操作之间建立了一个依赖链,并在其间执行布局转换,并且不会在之前的工作和任何光栅化前着色器阶段之间引入依赖关系。更准确地说,信号量会在呈现操作完成后发出信号,信号量等待会阻塞 |
等待操作的信号量状态要求
在等待信号量之前,应用程序必须确保信号量处于等待操作的有效状态。具体而言,当一个信号量等待操作被提交到队列时
信号量上的主机操作
-
使用vkGetSemaphoreCounterValue命令查询信号量的当前计数器值。
-
使用vkWaitSemaphores命令等待一组信号量达到特定的计数器值。
-
使用vkSignalSemaphore命令从主机发出具有特定计数器值的信号量。
要从主机查询使用VK_SEMAPHORE_TYPE_TIMELINE
的VkSemaphoreType创建的信号量的当前计数器值,请调用
// Provided by VK_VERSION_1_2
VkResult vkGetSemaphoreCounterValue(
VkDevice device,
VkSemaphore semaphore,
uint64_t* pValue);
或等效命令
// Provided by VK_KHR_timeline_semaphore
VkResult vkGetSemaphoreCounterValueKHR(
VkDevice device,
VkSemaphore semaphore,
uint64_t* pValue);
-
device
是拥有该信号量的逻辑设备。 -
semaphore
是要查询的信号量的句柄。 -
pValue
是指向一个64位整数值的指针,该整数值将返回信号量的当前计数器值。
如果队列提交命令正在等待执行,则此命令返回的值可能会立即过时。 |
要等待使用VK_SEMAPHORE_TYPE_TIMELINE
的VkSemaphoreType创建的一组信号量在主机上达到特定的计数器值,请调用
// Provided by VK_VERSION_1_2
VkResult vkWaitSemaphores(
VkDevice device,
const VkSemaphoreWaitInfo* pWaitInfo,
uint64_t timeout);
或等效命令
// Provided by VK_KHR_timeline_semaphore
VkResult vkWaitSemaphoresKHR(
VkDevice device,
const VkSemaphoreWaitInfo* pWaitInfo,
uint64_t timeout);
-
device
是拥有信号量的逻辑设备。 -
pWaitInfo
是指向VkSemaphoreWaitInfo结构的指针,该结构包含有关等待条件的信息。 -
timeout
是以纳秒为单位的超时时间。timeout
会调整为实现定义的超时精度所允许的最接近的值,该值可能比一纳秒长得多,并且可能比请求的时间长。
如果在调用vkWaitSemaphores
时条件已满足,则vkWaitSemaphores
会立即返回。如果在调用vkWaitSemaphores
时条件未满足,则vkWaitSemaphores
会阻塞并等待直到条件满足或timeout
过期,以较早者为准。
如果timeout
为零,则vkWaitSemaphores
不会等待,而只是返回有关信号量当前状态的信息。如果条件未满足,则在这种情况下会返回VK_TIMEOUT
,即使没有执行实际的等待。
如果条件在timeout
过期之前满足,则vkWaitSemaphores
会返回VK_SUCCESS
。否则,vkWaitSemaphores
会在timeout
过期后返回VK_TIMEOUT
。
如果在超时过期之前发生设备丢失(请参阅丢失设备),则vkWaitSemaphores
必须在有限的时间内返回VK_SUCCESS
或VK_ERROR_DEVICE_LOST
。
VkSemaphoreWaitInfo
结构定义如下
// Provided by VK_VERSION_1_2
typedef struct VkSemaphoreWaitInfo {
VkStructureType sType;
const void* pNext;
VkSemaphoreWaitFlags flags;
uint32_t semaphoreCount;
const VkSemaphore* pSemaphores;
const uint64_t* pValues;
} VkSemaphoreWaitInfo;
或等效的
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreWaitInfo VkSemaphoreWaitInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是VkSemaphoreWaitFlagBits的位掩码,用于指定信号量等待操作的附加参数。 -
semaphoreCount
是要等待的信号量的数量。 -
pSemaphores
是指向要等待的semaphoreCount
信号量句柄数组的指针。 -
pValues
是指向semaphoreCount
时间线信号量值数组的指针。
在 VkSemaphoreWaitInfo::flags
中可以设置的位,用于指定信号量等待操作的附加参数,包括:
// Provided by VK_VERSION_1_2
typedef enum VkSemaphoreWaitFlagBits {
VK_SEMAPHORE_WAIT_ANY_BIT = 0x00000001,
// Provided by VK_KHR_timeline_semaphore
VK_SEMAPHORE_WAIT_ANY_BIT_KHR = VK_SEMAPHORE_WAIT_ANY_BIT,
} VkSemaphoreWaitFlagBits;
或等效的
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreWaitFlagBits VkSemaphoreWaitFlagBitsKHR;
-
VK_SEMAPHORE_WAIT_ANY_BIT
指定信号量等待条件为VkSemaphoreWaitInfo
::pSemaphores
中的至少一个信号量已达到VkSemaphoreWaitInfo
::pValues
的相应元素指定的值。如果未设置VK_SEMAPHORE_WAIT_ANY_BIT
,则信号量等待条件为VkSemaphoreWaitInfo
::pSemaphores
中的所有信号量都已达到VkSemaphoreWaitInfo
::pValues
的相应元素指定的值。
// Provided by VK_VERSION_1_2
typedef VkFlags VkSemaphoreWaitFlags;
或等效的
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreWaitFlags VkSemaphoreWaitFlagsKHR;
VkSemaphoreWaitFlags
是一种位掩码类型,用于设置零个或多个 VkSemaphoreWaitFlagBits 的掩码。
要在主机上使用特定的计数器值来发出 VkSemaphoreType 为 VK_SEMAPHORE_TYPE_TIMELINE
的信号量信号,请调用
// Provided by VK_VERSION_1_2
VkResult vkSignalSemaphore(
VkDevice device,
const VkSemaphoreSignalInfo* pSignalInfo);
或等效命令
// Provided by VK_KHR_timeline_semaphore
VkResult vkSignalSemaphoreKHR(
VkDevice device,
const VkSemaphoreSignalInfo* pSignalInfo);
-
device
是拥有该信号量的逻辑设备。 -
pSignalInfo
是指向 VkSemaphoreSignalInfo 结构的指针,该结构包含有关信号操作的信息。
当在主机上执行 vkSignalSemaphore
时,它会定义并立即执行一个 信号量信号操作,该操作将时间线信号量设置为给定值。
第一个同步范围由主机执行模型定义,但包括在主机上执行 vkSignalSemaphore
以及它之前发生的任何事情。
第二个同步范围为空。
VkSemaphoreSignalInfo
结构定义如下:
// Provided by VK_VERSION_1_2
typedef struct VkSemaphoreSignalInfo {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
uint64_t value;
} VkSemaphoreSignalInfo;
或等效的
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreSignalInfo VkSemaphoreSignalInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphore
是要发出信号的信号量的句柄。 -
value
是要发出的信号的值。
导入信号量有效负载
应用程序可以使用外部信号量句柄将信号量有效负载导入到现有信号量中。导入操作的效果将是临时的或永久的,由应用程序指定。如果导入是临时的,则在提交下一个信号量等待操作后,实现必须将信号量恢复到其先前的永久状态。在执行信号量等待之前,对信号量执行后续的临时导入对此要求没有影响;对信号量提交的下一个等待必须仍然恢复其最后一个永久状态。永久有效负载导入的行为就像目标信号量被销毁,并且创建了一个具有相同句柄但导入有效负载的新信号量。由于临时或永久导入信号量有效负载会将现有有效负载与信号量分离,因此任何导入信号量有效负载的命令都将应用与 vkDestroySemaphore
应用的类似使用限制。这些导入类型中的哪一种被使用被称为导入操作的持久性。每种句柄类型都支持一种或两种持久性类型。
实现必须通过引用或复制指定的外部信号量句柄所引用的有效负载来执行导入操作,具体取决于句柄的类型。所使用的导入方法被称为句柄类型的传递。当使用具有引用传递的句柄类型时,将有效负载导入到信号量会将该信号量添加到共享该有效负载的所有信号量集中。此集合包括从中导出有效负载的信号量。对集合中的任何信号量执行的信号量发出信号和等待操作的必须行为就像集合是一个信号量一样。使用具有复制传递的句柄类型导入有效负载会在导入时创建有效负载的重复副本,但不再引用它。对复制导入的目标执行的信号量发出信号和等待操作的必须不影响任何其他信号量或有效负载。
导出操作具有与指定句柄类型的导入操作相同的传递。此外,将信号量有效负载导出到具有复制传递的句柄会对源信号量的有效负载产生与执行信号量等待操作相同的副作用。如果信号量正在使用临时导入的有效负载,则信号量的先前永久有效负载将恢复。
句柄类型的持久性和传递可以在以下位置找到: |
外部同步 允许实现修改对象的内部状态(即有效负载),而无需内部同步。但是,对于跨进程共享有效负载的信号量,满足 VkSemaphore
参数的外部同步要求(就像集合中的所有信号量都是同一对象一样)有时是不可行的。满足等待操作状态要求同样需要在进程之间进行不切实际的协调或信任级别。因此,这些约束仅适用于特定的信号量句柄,而不适用于其有效负载。对于共享有效负载的不同信号量对象,如果信号量同时传递给单独的队列提交命令,则行为将如同命令以任意顺序调用一样。如果等待操作状态要求被队列提交命令违反了共享有效负载,或者如果为已经发出信号或有挂起信号操作的共享有效负载排队了一个信号操作,则效果必须限于以下一项或多项:
-
从导致违规的命令返回
VK_ERROR_INITIALIZATION_FAILED
。 -
立即或在未来某个时间丢失发生违规的逻辑设备,导致后续命令(包括导致违规的命令)返回
VK_ERROR_DEVICE_LOST
错误。 -
在实现相关的超时后,继续执行违规的命令或操作,如同信号量等待成功完成一样。在这种情况下,负载的状态变为未定义,并且对共享负载的信号量的未来操作将遵守相同的规则。信号量必须被销毁或其负载被导入操作替换,才能再次具有明确定义的状态。
这些规则允许进程同步对共享内存的访问,而无需彼此信任。但是,这些进程仍然必须小心,不要将共享信号量用于同步访问共享内存之外的其他用途。例如,如果进程不信任其他共享信号量负载的进程,则不应将共享信号量用作执行依赖链的一部分,该依赖链在完成时会导致对象被销毁。 |
当信号量使用导入的负载时,其 VkExportSemaphoreCreateInfo::handleTypes
值是在创建导出负载的信号量时指定的,而不是在创建信号量时指定的。此外,VkExternalSemaphoreProperties::exportFromImportedHandleTypes
限制了哪些句柄类型可以从这样的信号量导出,这取决于用于导入当前负载的特定句柄类型。将信号量传递给 vkAcquireNextImageKHR 等效于临时将信号量负载导入到该信号量中。
由于导入信号量的可导出句柄类型与其当前导入的负载相对应,并且 vkAcquireNextImageKHR 的行为与临时导入操作相同,其中源信号量对应用程序是不透明的,因此应用程序无法确定是否可以从处于此状态的信号量导出任何外部句柄类型。因此,应用程序必须不要尝试从使用 vkAcquireNextImageKHR 临时导入的负载的信号量导出外部句柄。 |
导入信号量负载时,应用程序有责任确保外部句柄满足所有有效的使用要求。但是,实现必须对外部句柄执行充分的验证,以确保该操作产生有效的信号量,该信号量在使用时不会导致程序终止、设备丢失、队列停滞或破坏其他资源(根据其导入参数允许使用,并排除违反 等待操作的有效信号量状态 规则所允许的副作用)。如果提供的外部句柄不满足这些要求,则实现必须使用错误代码 VK_ERROR_INVALID_EXTERNAL_HANDLE
来使信号量负载导入操作失败。
此外,当导入与信号量创建时对应的 VkSemaphoreType 的负载类型不兼容的信号量负载时,实现可能会使用错误代码 VK_ERROR_INVALID_EXTERNAL_HANDLE
使信号量负载导入操作失败。
由于外部信号量句柄类型 |
要从 Windows 句柄导入信号量负载,请调用
// Provided by VK_KHR_external_semaphore_win32
VkResult vkImportSemaphoreWin32HandleKHR(
VkDevice device,
const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
-
device
是创建信号量的逻辑设备。 -
pImportSemaphoreWin32HandleInfo
是指向 VkImportSemaphoreWin32HandleInfoKHR 结构的指针,该结构指定信号量和导入参数。
从 Windows 句柄导入信号量负载不会将句柄的所有权转移到 Vulkan 实现。对于定义为 NT 句柄的句柄类型,应用程序必须在不再需要该句柄时使用 CloseHandle
系统调用释放所有权。
应用程序可以将同一信号量负载导入到 Vulkan 的多个实例中,导入到导出它的同一实例中,以及多次导入到给定的 Vulkan 实例中。
VkImportSemaphoreWin32HandleInfoKHR
结构定义如下
// Provided by VK_KHR_external_semaphore_win32
typedef struct VkImportSemaphoreWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkSemaphoreImportFlags flags;
VkExternalSemaphoreHandleTypeFlagBits handleType;
HANDLE handle;
LPCWSTR name;
} VkImportSemaphoreWin32HandleInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphore
是要将负载导入的信号量。 -
flags
是一个 VkSemaphoreImportFlagBits 的位掩码,指定信号量负载导入操作的其他参数。 -
handleType
是一个 VkExternalSemaphoreHandleTypeFlagBits 值,指定handle
的类型。 -
handle
是NULL
或要导入的外部句柄。 -
name
是NULL
或一个以 null 结尾的 UTF-16 字符串,命名要导入的底层同步原语。
handleType
支持的句柄类型为
句柄类型 | 转移方式 | 支持的持久性 |
---|---|---|
|
参考 |
临时,永久 |
|
参考 |
临时,永久 |
|
参考 |
临时,永久 |
要从 POSIX 文件描述符导入信号量有效负载,请调用
// Provided by VK_KHR_external_semaphore_fd
VkResult vkImportSemaphoreFdKHR(
VkDevice device,
const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo);
-
device
是创建信号量的逻辑设备。 -
pImportSemaphoreFdInfo
是一个指向 VkImportSemaphoreFdInfoKHR 结构的指针,该结构指定信号量和导入参数。
从文件描述符导入信号量有效负载会将文件描述符的所有权从应用程序转移到 Vulkan 实现。成功导入后,应用程序必须不对文件描述符执行任何操作。
应用程序可以将同一信号量负载导入到 Vulkan 的多个实例中,导入到导出它的同一实例中,以及多次导入到给定的 Vulkan 实例中。
VkImportSemaphoreFdInfoKHR
结构定义如下:
// Provided by VK_KHR_external_semaphore_fd
typedef struct VkImportSemaphoreFdInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkSemaphoreImportFlags flags;
VkExternalSemaphoreHandleTypeFlagBits handleType;
int fd;
} VkImportSemaphoreFdInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphore
是要将负载导入的信号量。 -
flags
是一个 VkSemaphoreImportFlagBits 的位掩码,指定信号量负载导入操作的其他参数。 -
handleType
是一个 VkExternalSemaphoreHandleTypeFlagBits 值,指定fd
的类型。 -
fd
是要导入的外部句柄。
handleType
支持的句柄类型为
句柄类型 | 转移方式 | 支持的持久性 |
---|---|---|
|
参考 |
临时,永久 |
|
复制 |
临时 |
如果 handleType
是 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
,则 fd
的特殊值 -1
将被视为引用已发出信号的对象的有效同步文件描述符。导入操作将成功,并且 VkSemaphore
将具有临时导入的有效负载,就像已提供有效的文件描述符一样。
导入无效同步文件描述符的这种特殊行为可以更容易地与其他系统 API 互操作,这些 API 使用无效同步文件描述符表示已完成且无需等待的工作的约定。这与实现返回一个 |
要从 Zircon 事件句柄导入信号量有效负载,请调用
// Provided by VK_FUCHSIA_external_semaphore
VkResult vkImportSemaphoreZirconHandleFUCHSIA(
VkDevice device,
const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo);
-
device
是创建信号量的逻辑设备。 -
pImportSemaphoreZirconHandleInfo
是一个指向 VkImportSemaphoreZirconHandleInfoFUCHSIA 结构的指针,该结构指定信号量和导入参数。
从 Zircon 事件句柄导入信号量有效负载会将句柄的所有权从应用程序转移到 Vulkan 实现。成功导入后,应用程序必须不对该句柄执行任何操作。
应用程序可以将同一信号量负载导入到 Vulkan 的多个实例中,导入到导出它的同一实例中,以及多次导入到给定的 Vulkan 实例中。
VkImportSemaphoreZirconHandleInfoFUCHSIA
结构定义如下:
// Provided by VK_FUCHSIA_external_semaphore
typedef struct VkImportSemaphoreZirconHandleInfoFUCHSIA {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkSemaphoreImportFlags flags;
VkExternalSemaphoreHandleTypeFlagBits handleType;
zx_handle_t zirconHandle;
} VkImportSemaphoreZirconHandleInfoFUCHSIA;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
semaphore
是要将负载导入的信号量。 -
flags
是一个 VkSemaphoreImportFlagBits 的位掩码,指定信号量负载导入操作的其他参数。 -
handleType
是一个 VkExternalSemaphoreHandleTypeFlagBits 值,指定zirconHandle
的类型。 -
zirconHandle
是要导入的外部句柄。
handleType
支持的句柄类型为
句柄类型 | 转移方式 | 支持的持久性 |
---|---|---|
|
参考 |
临时,永久 |
可在以下项中设置的位
指定信号量导入操作的附加参数为
// Provided by VK_VERSION_1_1
typedef enum VkSemaphoreImportFlagBits {
VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001,
// Provided by VK_KHR_external_semaphore
VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
} VkSemaphoreImportFlagBits;
或等效的
// Provided by VK_KHR_external_semaphore
typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR;
这些位具有以下含义
-
VK_SEMAPHORE_IMPORT_TEMPORARY_BIT
指定信号量有效载荷将仅临时导入,如导入信号量有效载荷中所述,无论handleType
的持久性如何。
// Provided by VK_VERSION_1_1
typedef VkFlags VkSemaphoreImportFlags;
或等效的
// Provided by VK_KHR_external_semaphore
typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR;
VkSemaphoreImportFlags
是一种位掩码类型,用于设置零个或多个 VkSemaphoreImportFlagBits 的掩码。
事件
事件是一种同步原语,可以用于在提交到同一队列的命令之间,或在主机和队列之间插入细粒度的依赖关系。事件必须不用于在提交到不同队列的命令之间插入依赖关系。事件有两种状态 - 已发出信号和未发出信号。应用程序可以在主机或设备上发出信号或取消发出事件信号。可以使设备在执行进一步操作之前等待事件变为已发出信号。没有命令可以等待主机上事件变为已发出信号,但是可以查询事件的当前状态。
事件由 VkEvent
句柄表示
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent)
要创建事件,请调用
// Provided by VK_VERSION_1_0
VkResult vkCreateEvent(
VkDevice device,
const VkEventCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkEvent* pEvent);
-
device
是创建事件的逻辑设备。 -
pCreateInfo
是指向 VkEventCreateInfo 结构的指针,其中包含有关如何创建事件的信息。 -
pAllocator
控制主机内存分配,具体描述请参考内存分配章节。 -
pEvent
是指向返回的结果事件对象的句柄的指针。
创建时,事件对象处于未发出信号的状态。
VkEventCreateInfo
结构定义如下
// Provided by VK_VERSION_1_0
typedef struct VkEventCreateInfo {
VkStructureType sType;
const void* pNext;
VkEventCreateFlags flags;
} VkEventCreateInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
是 VkEventCreateFlagBits 的位掩码,定义了额外的创建参数。
// Provided by VK_VERSION_1_0
typedef enum VkEventCreateFlagBits {
// Provided by VK_VERSION_1_3
VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0x00000001,
// Provided by VK_KHR_synchronization2
VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = VK_EVENT_CREATE_DEVICE_ONLY_BIT,
} VkEventCreateFlagBits;
-
VK_EVENT_CREATE_DEVICE_ONLY_BIT
指定主机事件命令不会与此事件一起使用。
// Provided by VK_VERSION_1_0
typedef VkFlags VkEventCreateFlags;
VkEventCreateFlags
是一种位掩码类型,用于设置 VkEventCreateFlagBits 的掩码。
要销毁事件,请调用
// Provided by VK_VERSION_1_0
void vkDestroyEvent(
VkDevice device,
VkEvent event,
const VkAllocationCallbacks* pAllocator);
-
device
是销毁事件的逻辑设备。 -
event
是要销毁的事件的句柄。 -
pAllocator
控制主机内存分配,具体描述请参考内存分配章节。
要从主机查询事件的状态,请调用
// Provided by VK_VERSION_1_0
VkResult vkGetEventStatus(
VkDevice device,
VkEvent event);
-
device
是拥有事件的逻辑设备。 -
event
是要查询的事件的句柄。
成功后,vkGetEventStatus
返回事件对象的状态,并带有以下返回码
状态 | 含义 |
---|---|
|
|
|
由 |
如果 vkCmdSetEvent
或 vkCmdResetEvent
命令在一个处于挂起状态的命令缓冲区中,则此命令返回的值可能会立即过时。
事件的状态可以由主机更新。事件的状态会立即更改,并且随后对 vkGetEventStatus
的调用将返回新的状态。如果事件已处于请求的状态,则将其更新为相同的状态无效。
要将事件的状态从主机设置为信号状态,请调用
// Provided by VK_VERSION_1_0
VkResult vkSetEvent(
VkDevice device,
VkEvent event);
-
device
是拥有事件的逻辑设备。 -
event
是要设置的事件。
当在主机上执行 vkSetEvent 时,它会定义一个事件信号操作,该操作将事件设置为信号状态。
如果 event
在执行 vkSetEvent 时已处于信号状态,则 vkSetEvent 不会产生任何影响,并且不会发生事件信号操作。
如果命令缓冲区正在等待主机发出事件信号,则应用程序必须在提交命令缓冲区之前发出事件信号,如队列前进部分所述。 |
要将事件的状态从主机设置为未信号状态,请调用
// Provided by VK_VERSION_1_0
VkResult vkResetEvent(
VkDevice device,
VkEvent event);
-
device
是拥有事件的逻辑设备。 -
event
是要重置的事件。
当在主机上执行 vkResetEvent 时,它会定义一个事件未信号操作,该操作将事件重置为未信号状态。
如果 event
在执行 vkResetEvent 时已处于未信号状态,则 vkResetEvent 不会产生任何影响,并且不会发生事件未信号操作。
事件的状态可以通过插入到命令缓冲区中的命令在设备上更新。
要从设备发出事件信号,请调用
// Provided by VK_VERSION_1_3
void vkCmdSetEvent2(
VkCommandBuffer commandBuffer,
VkEvent event,
const VkDependencyInfo* pDependencyInfo);
或等效命令
// Provided by VK_KHR_synchronization2
void vkCmdSetEvent2KHR(
VkCommandBuffer commandBuffer,
VkEvent event,
const VkDependencyInfo* pDependencyInfo);
-
commandBuffer
是将命令记录到的命令缓冲区。 -
event
是将被信号化的事件。 -
pDependencyInfo
是指向 VkDependencyInfo 结构的指针,该结构定义此操作的第一个作用域。
当 vkCmdSetEvent2 提交到队列时,它会定义 pDependencyInfo
定义的内存依赖关系的第一部分,以及将事件设置为信号状态的事件信号操作。在事件信号操作和按提交顺序较早发生的命令之间定义了内存依赖关系。
第一个同步作用域和访问作用域由pDependencyInfo
定义的所有内存依赖关系的并集定义,并且应用于所有在提交顺序中较早发生的操作。队列族所有权转移和 pDependencyInfo
定义的图像布局转换也包含在第一个作用域中。
未来的 vkCmdWaitEvents2 命令依赖于 pDependencyInfo
中每个元素的所有值与用于信号化相应事件的值完全匹配。vkCmdWaitEvents 必须不能用于等待 vkCmdSetEvent2
定义的信号操作的结果。
与 vkCmdSetEvent 相比,vkCmdSetEvent2 提供的额外信息允许实现更有效地调度满足请求依赖关系所需的操作。使用 vkCmdSetEvent,直到记录 vkCmdWaitEvents 时才知道完整的依赖关系信息,这迫使实现程序在该点而不是之前插入所需的操作。 |
如果 event
在设备上执行 vkCmdSetEvent2 时已处于信号状态,则 vkCmdSetEvent2 不会产生任何影响,不会发生事件信号操作,也不会生成依赖关系。
VkDependencyInfo
结构定义如下
// Provided by VK_VERSION_1_3
typedef struct VkDependencyInfo {
VkStructureType sType;
const void* pNext;
VkDependencyFlags dependencyFlags;
uint32_t memoryBarrierCount;
const VkMemoryBarrier2* pMemoryBarriers;
uint32_t bufferMemoryBarrierCount;
const VkBufferMemoryBarrier2* pBufferMemoryBarriers;
uint32_t imageMemoryBarrierCount;
const VkImageMemoryBarrier2* pImageMemoryBarriers;
} VkDependencyInfo;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkDependencyInfo VkDependencyInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
dependencyFlags
是 VkDependencyFlagBits 的位掩码,用于指定如何形成执行和内存依赖项。 -
memoryBarrierCount
是pMemoryBarriers
数组的长度。 -
pMemoryBarriers
是指向 VkMemoryBarrier2 结构数组的指针,这些结构定义了任何内存访问之间的内存依赖项。 -
bufferMemoryBarrierCount
是pBufferMemoryBarriers
数组的长度。 -
pBufferMemoryBarriers
是指向 VkBufferMemoryBarrier2 结构数组的指针,这些结构定义了缓冲区范围之间的内存依赖项。 -
imageMemoryBarrierCount
是pImageMemoryBarriers
数组的长度。 -
pImageMemoryBarriers
是指向 VkImageMemoryBarrier2 结构数组的指针,这些结构定义了图像子资源之间的内存依赖项。
此结构定义了一组内存依赖项,以及队列族所有权转移操作和图像布局转换。
pMemoryBarriers
、pBufferMemoryBarriers
和 pImageMemoryBarriers
的每个成员都定义了一个单独的内存依赖项。
要将事件状态从设备设置为已发出信号,请调用
// Provided by VK_VERSION_1_0
void vkCmdSetEvent(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags stageMask);
vkCmdSetEvent
的行为与 vkCmdSetEvent2 相同,但它不定义访问范围,并且必须仅与 vkCmdWaitEvents 一起使用,而不是与 vkCmdWaitEvents2 一起使用。
要从设备取消事件的信号,请调用
// Provided by VK_VERSION_1_3
void vkCmdResetEvent2(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags2 stageMask);
或等效命令
// Provided by VK_KHR_synchronization2
void vkCmdResetEvent2KHR(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags2 stageMask);
-
commandBuffer
是将命令记录到的命令缓冲区。 -
event
是将被取消信号的事件。 -
stageMask
是VkPipelineStageFlags2掩码,用于确定第一个同步范围。
当vkCmdResetEvent2提交到队列时,它定义了对之前提交的命令的执行依赖关系,并定义了一个事件取消信号操作,该操作将事件重置为未信号状态。
第二个同步范围仅包括事件取消信号操作。
如果当vkCmdResetEvent2在设备上执行时,event
已经处于未信号状态,则此命令不起作用,不发生事件取消信号操作,也不会生成执行依赖关系。
要将事件的状态从设备设置为未发出信号,请调用
// Provided by VK_VERSION_1_0
void vkCmdResetEvent(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags stageMask);
-
commandBuffer
是将命令记录到的命令缓冲区。 -
event
是将被取消信号的事件。 -
stageMask
是一个 VkPipelineStageFlagBits 的位掩码,指定用于确定event
何时未发出信号的源阶段掩码。
vkCmdResetEvent
的行为与 vkCmdResetEvent2 完全相同。
要等待一个或多个事件在设备上进入已触发状态,请调用
// Provided by VK_VERSION_1_3
void vkCmdWaitEvents2(
VkCommandBuffer commandBuffer,
uint32_t eventCount,
const VkEvent* pEvents,
const VkDependencyInfo* pDependencyInfos);
或等效命令
// Provided by VK_KHR_synchronization2
void vkCmdWaitEvents2KHR(
VkCommandBuffer commandBuffer,
uint32_t eventCount,
const VkEvent* pEvents,
const VkDependencyInfo* pDependencyInfos);
-
commandBuffer
是将命令记录到的命令缓冲区。 -
eventCount
是pEvents
数组的长度。 -
pEvents
是指向一个eventCount
个事件的数组的指针,这些事件将被等待。 -
pDependencyInfos
是指向一个eventCount
个 VkDependencyInfo 结构的数组的指针,定义了第二个同步范围。
当 vkCmdWaitEvents2
被提交到队列时,它会根据 pDependencyInfos
的元素和 pEvents
的每个对应元素插入内存依赖关系。vkCmdWaitEvents2
**必须** 不用于等待发生在其他队列上的事件触发操作,或由 vkCmdSetEvent 执行的触发操作。
只有在以下情况下,才会包含索引为 i 的事件的触发操作
-
该事件是由 vkCmdSetEvent2 命令触发的,该命令在提交顺序中较早发生,并且
dependencyInfo
参数与pDependencyInfos
中索引为 i 的元素完全相同;或者 -
该事件是在没有
VK_EVENT_CREATE_DEVICE_ONLY_BIT
的情况下创建的,并且pDependencyInfos
中索引为 i 的元素定义的第一个同步范围仅包括主机操作 (VK_PIPELINE_STAGE_2_HOST_BIT
)。
vkCmdWaitEvents2 与 vkCmdSetEvent2 一起使用,以定义两组操作命令之间的内存依赖关系,大致与管道屏障的方式相同,但分为两个命令,以便两者之间进行的工作**可能**不受阻碍地执行。 |
应用程序在使用事件时应小心避免竞争条件。 |
要等待一个或多个事件在设备上进入已触发状态,请调用
// Provided by VK_VERSION_1_0
void vkCmdWaitEvents(
VkCommandBuffer commandBuffer,
uint32_t eventCount,
const VkEvent* pEvents,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
uint32_t memoryBarrierCount,
const VkMemoryBarrier* pMemoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers);
-
commandBuffer
是将命令记录到的命令缓冲区。 -
eventCount
是pEvents
数组的长度。 -
pEvents
是指向要等待的事件对象句柄数组的指针。 -
srcStageMask
是一个 VkPipelineStageFlagBits 的位掩码,指定源阶段掩码。 -
dstStageMask
是一个 VkPipelineStageFlagBits 的位掩码,指定目标阶段掩码。 -
memoryBarrierCount
是pMemoryBarriers
数组的长度。 -
pMemoryBarriers
是指向 VkMemoryBarrier 结构体数组的指针。 -
bufferMemoryBarrierCount
是pBufferMemoryBarriers
数组的长度。 -
pBufferMemoryBarriers
是指向 VkBufferMemoryBarrier 结构体数组的指针。 -
imageMemoryBarrierCount
是pImageMemoryBarriers
数组的长度。 -
pImageMemoryBarriers
是指向 VkImageMemoryBarrier 结构体数组的指针。
vkCmdWaitEvents
在很大程度上与 vkCmdWaitEvents2 相似,但只能等待由 vkCmdSetEvent 定义的信号操作。由于 vkCmdSetEvent 没有定义任何访问范围,vkCmdWaitEvents
除了自己的访问范围外,还为每个事件信号操作定义了第一个访问范围。
由于 vkCmdSetEvent 除了阶段掩码之外没有任何依赖信息,因此实现没有与 vkCmdSetEvent2 和 vkCmdWaitEvents2 相同的机会来提前执行可用性和可见性操作或图像布局转换。 |
当 vkCmdWaitEvents
提交到队列时,它会在同一队列或主机上的先前事件信号操作与后续命令之间定义一个内存依赖关系。不能使用 vkCmdWaitEvents
来等待发生在其他队列上的事件信号操作。
第一个同步范围仅包括对 pEvents
成员进行操作的事件信号操作,以及发生在事件信号操作之前的操作。如果它们的 stageMask
参数中的逻辑上最新的管线阶段逻辑上早于或等于 srcStageMask
中的逻辑上最新的管线阶段,则由 vkCmdSetEvent 执行的在提交顺序中较早发生的事件信号操作包含在第一个同步范围中。如果 VK_PIPELINE_STAGE_HOST_BIT
包含在 srcStageMask
中,则只有由 vkSetEvent 执行的事件信号操作才包含在第一个同步范围中。
管线屏障
要记录管线屏障,请调用
// Provided by VK_VERSION_1_3
void vkCmdPipelineBarrier2(
VkCommandBuffer commandBuffer,
const VkDependencyInfo* pDependencyInfo);
或等效命令
// Provided by VK_KHR_synchronization2
void vkCmdPipelineBarrier2KHR(
VkCommandBuffer commandBuffer,
const VkDependencyInfo* pDependencyInfo);
-
commandBuffer
是将命令记录到的命令缓冲区。 -
pDependencyInfo
是指向 VkDependencyInfo 结构的指针,该结构定义了此操作的范围。
当将 vkCmdPipelineBarrier2 提交到队列时,它定义了在它之前提交到同一队列的命令与在它之后提交到同一队列的命令之间的内存依赖关系。
如果在渲染过程实例中记录了 vkCmdPipelineBarrier2
,则同步范围将限制为同一子过程或渲染过程实例中的操作子集。
要记录管线屏障,请调用
// Provided by VK_VERSION_1_0
void vkCmdPipelineBarrier(
VkCommandBuffer commandBuffer,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkDependencyFlags dependencyFlags,
uint32_t memoryBarrierCount,
const VkMemoryBarrier* pMemoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers);
-
commandBuffer
是将命令记录到的命令缓冲区。 -
srcStageMask
是一个VkPipelineStageFlagBits的位掩码,指定源阶段。 -
dstStageMask
是一个VkPipelineStageFlagBits的位掩码,指定目标阶段。 -
dependencyFlags
是 VkDependencyFlagBits 的位掩码,用于指定如何形成执行和内存依赖项。 -
memoryBarrierCount
是pMemoryBarriers
数组的长度。 -
pMemoryBarriers
是指向 VkMemoryBarrier 结构体数组的指针。 -
bufferMemoryBarrierCount
是pBufferMemoryBarriers
数组的长度。 -
pBufferMemoryBarriers
是指向 VkBufferMemoryBarrier 结构体数组的指针。 -
imageMemoryBarrierCount
是pImageMemoryBarriers
数组的长度。 -
pImageMemoryBarriers
是指向 VkImageMemoryBarrier 结构体数组的指针。
vkCmdPipelineBarrier
的操作几乎与 vkCmdPipelineBarrier2 相同,除了作用域和屏障被定义为直接参数,而不是由 VkDependencyInfo 定义。
当 vkCmdPipelineBarrier 提交到队列时,它定义了在其之前提交到同一队列的命令和在其之后提交到同一队列的命令之间的内存依赖关系。
如果 vkCmdPipelineBarrier 在渲染通道实例之外记录,则第一个同步范围包括在提交顺序中较早发生的所有命令。如果 vkCmdPipelineBarrier 在渲染通道实例内部记录,则第一个同步范围仅包括在同一子通道内的提交顺序中较早发生的命令。在任何一种情况下,第一个同步范围都限于由 srcStageMask
指定的源阶段掩码确定的管线阶段的操作。
如果 vkCmdPipelineBarrier 在渲染通道实例之外记录,则第二个同步范围包括在提交顺序中较晚发生的所有命令。如果 vkCmdPipelineBarrier 在渲染通道实例内部记录,则第二个同步范围仅包括在同一子通道内的提交顺序中较晚发生的命令。在任何一种情况下,第二个同步范围都限于由 dstStageMask
指定的目标阶段掩码确定的管线阶段的操作。
第一个访问范围仅限于由 srcStageMask
指定的源阶段掩码确定的管线阶段中的访问。其中,第一个访问范围仅包括由 pMemoryBarriers
、pBufferMemoryBarriers
和 pImageMemoryBarriers
数组的元素定义的第一个访问范围,它们每个都定义了一组内存屏障。如果未指定任何内存屏障,则第一个访问范围不包含任何访问。
vkCmdPipelineBarrier
::dependencyFlags
中可以设置的位,指定执行和内存依赖关系如何形成,包括:
// Provided by VK_VERSION_1_0
typedef enum VkDependencyFlagBits {
VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
// Provided by VK_VERSION_1_1
VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004,
// Provided by VK_VERSION_1_1
VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002,
// Provided by VK_EXT_attachment_feedback_loop_layout
VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT = 0x00000008,
// Provided by VK_KHR_maintenance8
VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR = 0x00000020,
// Provided by VK_KHR_multiview
VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT,
// Provided by VK_KHR_device_group
VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT,
} VkDependencyFlagBits;
-
VK_DEPENDENCY_BY_REGION_BIT
指定依赖关系将是帧缓冲局部的。 -
VK_DEPENDENCY_VIEW_LOCAL_BIT
指定依赖关系将是视图局部的。 -
VK_DEPENDENCY_DEVICE_GROUP_BIT
指定依赖关系是非设备局部的。 -
VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT
指定渲染过程将使用VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
布局写入并读取同一个图像。 -
VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
指定在执行 队列族所有权转移时,不忽略源阶段和目标阶段。
// Provided by VK_VERSION_1_0
typedef VkFlags VkDependencyFlags;
VkDependencyFlags
是一个位掩码类型,用于设置零个或多个 VkDependencyFlagBits 的掩码。
内存屏障
内存屏障用于显式控制对缓冲区和图像子资源范围的访问。内存屏障用于 在队列族之间转移所有权,更改图像布局,以及定义 可用性和可见性操作。它们显式定义 访问类型以及包含在由包含它们的同步命令创建的内存依赖关系的 访问范围 中的缓冲区和图像子资源范围。
全局内存屏障
全局内存屏障应用于执行时存在的所有内存对象的内存访问。
VkMemoryBarrier2
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkMemoryBarrier2 {
VkStructureType sType;
const void* pNext;
VkPipelineStageFlags2 srcStageMask;
VkAccessFlags2 srcAccessMask;
VkPipelineStageFlags2 dstStageMask;
VkAccessFlags2 dstAccessMask;
} VkMemoryBarrier2;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkMemoryBarrier2 VkMemoryBarrier2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcStageMask
是一个 VkPipelineStageFlags2 掩码,表示要包含在第一个同步范围中的管线阶段。 -
srcAccessMask
是一个 VkAccessFlags2 掩码,表示要包含在第一个访问范围中的访问标志。 -
dstStageMask
是一个 VkPipelineStageFlags2 掩码,表示要包含在第二个同步范围中的管线阶段。 -
dstAccessMask
是一个 VkAccessFlags2 掩码,表示要包含在第二个访问范围中的访问标志。
此结构定义一个影响所有设备内存的 内存依赖关系。
VkMemoryBarrier
结构定义如下:
// Provided by VK_VERSION_1_0
typedef struct VkMemoryBarrier {
VkStructureType sType;
const void* pNext;
VkAccessFlags srcAccessMask;
VkAccessFlags dstAccessMask;
} VkMemoryBarrier;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcAccessMask
是 VkAccessFlagBits 的位掩码,指定一个源访问掩码。 -
dstAccessMask
是 VkAccessFlagBits 的位掩码,指定一个目标访问掩码。
第一个 访问范围 被限制为 srcAccessMask
指定的源访问掩码中的访问类型,如果 pNext
中传递了 VkMemoryBarrierAccessFlags3KHR,则还包括 srcAccessMask3
。
第二个 访问范围 被限制为 dstAccessMask
指定的目标访问掩码中的访问类型,如果 pNext
中传递了 VkMemoryBarrierAccessFlags3KHR,则还包括 dstAccessMask3
。
缓冲区内存屏障
VkBufferMemoryBarrier2
结构定义如下:
// Provided by VK_VERSION_1_3
typedef struct VkBufferMemoryBarrier2 {
VkStructureType sType;
const void* pNext;
VkPipelineStageFlags2 srcStageMask;
VkAccessFlags2 srcAccessMask;
VkPipelineStageFlags2 dstStageMask;
VkAccessFlags2 dstAccessMask;
uint32_t srcQueueFamilyIndex;
uint32_t dstQueueFamilyIndex;
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize size;
} VkBufferMemoryBarrier2;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkBufferMemoryBarrier2 VkBufferMemoryBarrier2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcStageMask
是一个 VkPipelineStageFlags2 掩码,表示要包含在第一个同步范围中的管线阶段。 -
srcAccessMask
是一个 VkAccessFlags2 掩码,表示要包含在第一个访问范围中的访问标志。 -
dstStageMask
是一个 VkPipelineStageFlags2 掩码,表示要包含在第二个同步范围中的管线阶段。 -
dstAccessMask
是一个 VkAccessFlags2 掩码,表示要包含在第二个访问范围中的访问标志。 -
srcQueueFamilyIndex
是用于队列族所有权转移的源队列族。 -
dstQueueFamilyIndex
是用于队列族所有权转移的目标队列族。 -
buffer
是一个句柄,指向其后备内存受屏障影响的缓冲区。 -
offset
是buffer
的后备内存中的字节偏移量;这是相对于绑定到缓冲区的基本偏移量(请参阅vkBindBufferMemory)。 -
size
是buffer
的后备内存受影响区域的大小(以字节为单位),或者VK_WHOLE_SIZE
表示使用从offset
到缓冲区末尾的范围。
此结构定义了一个内存依赖关系,该依赖关系限定为一个缓冲区范围,并且可以为该范围定义一个队列族所有权转移操作。
两个访问范围都被限制为仅对 buffer
中 offset
和 size
定义的范围内的内存访问。
如果使用 VK_SHARING_MODE_EXCLUSIVE
创建 buffer
,并且 srcQueueFamilyIndex
不等于 dstQueueFamilyIndex
,则此内存屏障定义一个队列族所有权转移操作。在由 srcQueueFamilyIndex
标识的队列族中的队列上执行时,此屏障为指定的缓冲区范围定义一个队列族释放操作,并且如果 VkDependencyInfoKHR::dependencyFlags
未包含 VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则第二个同步范围不适用于此操作。在由 dstQueueFamilyIndex
标识的队列族中的队列上执行时,此屏障为指定的缓冲区范围定义一个队列族获取操作,并且如果 VkDependencyInfoKHR::dependencyFlags
未包含 VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则第一个同步范围不适用于此操作。
如果值不相等,且其中一个值是为外部内存所有权转移保留的特殊队列族值之一(如队列族所有权转移中所述),则还会定义队列族所有权转移操作。当 dstQueueFamilyIndex
是这些值之一时,会定义队列族释放操作;当 srcQueueFamilyIndex
是这些值之一时,会定义队列族获取操作。
VkBufferMemoryBarrier
结构的定义如下
// Provided by VK_VERSION_1_0
typedef struct VkBufferMemoryBarrier {
VkStructureType sType;
const void* pNext;
VkAccessFlags srcAccessMask;
VkAccessFlags dstAccessMask;
uint32_t srcQueueFamilyIndex;
uint32_t dstQueueFamilyIndex;
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize size;
} VkBufferMemoryBarrier;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcAccessMask
是 VkAccessFlagBits 的位掩码,指定一个源访问掩码。 -
dstAccessMask
是 VkAccessFlagBits 的位掩码,指定一个目标访问掩码。 -
srcQueueFamilyIndex
是用于队列族所有权转移的源队列族。 -
dstQueueFamilyIndex
是用于队列族所有权转移的目标队列族。 -
buffer
是一个句柄,指向其后备内存受屏障影响的缓冲区。 -
offset
是buffer
的后备内存中的字节偏移量;这是相对于绑定到缓冲区的基本偏移量(请参阅vkBindBufferMemory)。 -
size
是buffer
的后备内存受影响区域的大小(以字节为单位),或者VK_WHOLE_SIZE
表示使用从offset
到缓冲区末尾的范围。
第一个 访问范围 仅限于通过指定的缓冲区范围访问内存,通过 srcAccessMask
指定的源访问掩码中的访问类型,以及如果 pNext
中传递了 VkMemoryBarrierAccessFlags3KHR,则通过 srcAccessMask3
。如果源访问掩码包括 VK_ACCESS_HOST_WRITE_BIT
,则会执行内存域操作,其中主机域中的可用内存也会提供给设备域。
第二个 访问范围 仅限于通过指定的缓冲区范围访问内存,通过 dstAccessMask
指定的目标访问掩码中的访问类型,以及如果 pNext
中传递了 VkMemoryBarrierAccessFlags3KHR,则通过 dstAccessMask3
。如果目标访问掩码包括 VK_ACCESS_HOST_WRITE_BIT
或 VK_ACCESS_HOST_READ_BIT
,则会执行内存域操作,其中设备域中的可用内存也会提供给主机域。
当使用 |
如果 srcQueueFamilyIndex
不等于 dstQueueFamilyIndex
,并且 srcQueueFamilyIndex
等于当前队列族,则内存屏障为指定的缓冲区范围定义队列族释放操作,并且如果 dependencyFlags
未包含 VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则调用命令的第二个同步范围不适用于此操作。
如果 dstQueueFamilyIndex
不等于 srcQueueFamilyIndex
,并且 dstQueueFamilyIndex
等于当前队列族,则内存屏障为指定的缓冲区范围定义队列族获取操作,并且如果 dependencyFlags
未包含 VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则调用命令的第一个同步范围不适用于此操作。
VK_WHOLE_SIZE
是一个特殊值,表示应使用给定 offset
之后缓冲区的整个剩余长度。它可以为 VkBufferMemoryBarrier::size
和其他结构指定。
#define VK_WHOLE_SIZE (~0ULL)
图像内存屏障
图像内存屏障仅适用于涉及特定图像子资源范围的内存访问。也就是说,由图像内存屏障形成的内存依赖关系作用域到通过指定的图像子资源范围进行的访问。图像内存屏障也可以用于定义指定图像子资源范围的图像布局转换或队列族所有权转移。
VkImageMemoryBarrier2
结构的定义如下
// Provided by VK_VERSION_1_3
typedef struct VkImageMemoryBarrier2 {
VkStructureType sType;
const void* pNext;
VkPipelineStageFlags2 srcStageMask;
VkAccessFlags2 srcAccessMask;
VkPipelineStageFlags2 dstStageMask;
VkAccessFlags2 dstAccessMask;
VkImageLayout oldLayout;
VkImageLayout newLayout;
uint32_t srcQueueFamilyIndex;
uint32_t dstQueueFamilyIndex;
VkImage image;
VkImageSubresourceRange subresourceRange;
} VkImageMemoryBarrier2;
或等效的
// Provided by VK_KHR_synchronization2
typedef VkImageMemoryBarrier2 VkImageMemoryBarrier2KHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcStageMask
是一个 VkPipelineStageFlags2 掩码,表示要包含在第一个同步范围中的管线阶段。 -
srcAccessMask
是一个 VkAccessFlags2 掩码,表示要包含在第一个访问范围中的访问标志。 -
dstStageMask
是一个 VkPipelineStageFlags2 掩码,表示要包含在第二个同步范围中的管线阶段。 -
dstAccessMask
是一个 VkAccessFlags2 掩码,表示要包含在第二个访问范围中的访问标志。 -
oldLayout
是图像布局转换中的旧布局。 -
newLayout
是图像布局转换中的新布局。 -
srcQueueFamilyIndex
是用于队列族所有权转移的源队列族。 -
dstQueueFamilyIndex
是用于队列族所有权转移的目标队列族。 -
image
是受此屏障影响的图像的句柄。 -
subresourceRange
描述了image
中受此屏障影响的图像子资源范围。
此结构定义了一个限制在图像子资源范围内的内存依赖,并且可以为该子资源范围定义一个队列族所有权转移操作和一个图像布局转换。
两个访问范围都仅限于对image
在subresourceRange
定义的子资源范围内的内存访问。
如果image
是用VK_SHARING_MODE_EXCLUSIVE
创建的,并且srcQueueFamilyIndex
不等于dstQueueFamilyIndex
,则此内存屏障定义了一个队列族所有权转移操作。当在由srcQueueFamilyIndex
标识的族中的队列上执行时,此屏障为指定的图像子资源范围定义一个队列族释放操作,并且如果VkDependencyInfoKHR::dependencyFlags
不包含VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则第二个同步范围不适用于此操作。当在由dstQueueFamilyIndex
标识的族中的队列上执行时,此屏障为指定的图像子资源范围定义一个队列族获取操作,并且如果VkDependencyInfoKHR::dependencyFlags
不包含VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则第一个同步范围不适用于此操作。
如果值不相等,且其中一个值是为外部内存所有权转移保留的特殊队列族值之一(如队列族所有权转移中所述),则还会定义队列族所有权转移操作。当 dstQueueFamilyIndex
是这些值之一时,会定义队列族释放操作;当 srcQueueFamilyIndex
是这些值之一时,会定义队列族获取操作。
如果oldLayout
不等于newLayout
,则此内存屏障为指定的图像子资源范围定义一个图像布局转换。如果此内存屏障定义了一个队列族所有权转移操作,则布局转换仅在队列之间执行一次。
当旧布局和新布局相等时,布局值将被忽略 - 无论指定什么值或图像当前处于什么布局,数据都会被保留。 |
如果image
具有多平面格式且图像是不连续的,则在subresourceRange
的aspectMask
成员中包含VK_IMAGE_ASPECT_COLOR_BIT
等效于包含VK_IMAGE_ASPECT_PLANE_0_BIT
、VK_IMAGE_ASPECT_PLANE_1_BIT
和(仅对于三平面格式)VK_IMAGE_ASPECT_PLANE_2_BIT
。
VkImageMemoryBarrier
结构体的定义如下:
// Provided by VK_VERSION_1_0
typedef struct VkImageMemoryBarrier {
VkStructureType sType;
const void* pNext;
VkAccessFlags srcAccessMask;
VkAccessFlags dstAccessMask;
VkImageLayout oldLayout;
VkImageLayout newLayout;
uint32_t srcQueueFamilyIndex;
uint32_t dstQueueFamilyIndex;
VkImage image;
VkImageSubresourceRange subresourceRange;
} VkImageMemoryBarrier;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
srcAccessMask
是 VkAccessFlagBits 的位掩码,指定一个源访问掩码。 -
dstAccessMask
是 VkAccessFlagBits 的位掩码,指定一个目标访问掩码。 -
oldLayout
是图像布局转换中的旧布局。 -
newLayout
是图像布局转换中的新布局。 -
srcQueueFamilyIndex
是用于队列族所有权转移的源队列族。 -
dstQueueFamilyIndex
是用于队列族所有权转移的目标队列族。 -
image
是受此屏障影响的图像的句柄。 -
subresourceRange
描述了image
中受此屏障影响的图像子资源范围。
第一个访问范围被限制为通过指定的图像子资源范围访问内存,通过由srcAccessMask
指定的源访问掩码中的访问类型。如果srcAccessMask
包含VK_ACCESS_HOST_WRITE_BIT
,则该访问类型执行的内存写入也将变得可见,因为该访问类型不是通过资源执行的。
第二个访问范围被限制为通过指定的图像子资源范围访问内存,通过由dstAccessMask
指定的目标访问掩码中的访问类型。如果dstAccessMask
包含VK_ACCESS_HOST_WRITE_BIT
或VK_ACCESS_HOST_READ_BIT
,则可用的内存写入也会对这些类型的访问变得可见,因为这些访问类型不是通过资源执行的。
如果srcQueueFamilyIndex
不等于dstQueueFamilyIndex
,并且srcQueueFamilyIndex
等于当前队列族,则内存屏障为指定的图像子资源范围定义一个队列族释放操作,并且如果dependencyFlags
不包含VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则调用命令的第二个同步范围不适用于此操作。
如果dstQueueFamilyIndex
不等于srcQueueFamilyIndex
,并且dstQueueFamilyIndex
等于当前队列族,则内存屏障为指定的图像子资源范围定义一个队列族获取操作,并且如果dependencyFlags
不包含VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则调用命令的第一个同步范围不适用于此操作。
如果synchronization2
功能未启用或oldLayout
不等于newLayout
,则oldLayout
和newLayout
为指定的图像子资源范围定义一个图像布局转换。
如果 |
如果image
具有多平面格式且图像是不连续的,则在subresourceRange
的aspectMask
成员中包含VK_IMAGE_ASPECT_COLOR_BIT
等效于包含VK_IMAGE_ASPECT_PLANE_0_BIT
、VK_IMAGE_ASPECT_PLANE_1_BIT
和(仅对于三平面格式)VK_IMAGE_ASPECT_PLANE_2_BIT
。
为了方便在主机上初始化内存的图像的使用,Vulkan 允许主机执行图像布局转换,尽管支持的布局有限。
要在主机上执行图像布局转换,请调用
// Provided by VK_VERSION_1_4
VkResult vkTransitionImageLayout(
VkDevice device,
uint32_t transitionCount,
const VkHostImageLayoutTransitionInfo* pTransitions);
或等效命令
// Provided by VK_EXT_host_image_copy
VkResult vkTransitionImageLayoutEXT(
VkDevice device,
uint32_t transitionCount,
const VkHostImageLayoutTransitionInfo* pTransitions);
-
device
是拥有pTransitions
[i].image
的设备。 -
transitionCount
是要执行的图像布局转换的数量。 -
pTransitions
是指向VkHostImageLayoutTransitionInfo结构数组的指针,该结构指定要转换的图像及其中的子资源范围。
VkHostImageLayoutTransitionInfo
结构的定义如下:
// Provided by VK_VERSION_1_4
typedef struct VkHostImageLayoutTransitionInfo {
VkStructureType sType;
const void* pNext;
VkImage image;
VkImageLayout oldLayout;
VkImageLayout newLayout;
VkImageSubresourceRange subresourceRange;
} VkHostImageLayoutTransitionInfo;
或等效的
// Provided by VK_EXT_host_image_copy
typedef VkHostImageLayoutTransitionInfo VkHostImageLayoutTransitionInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
image
是受此布局转换影响的图像句柄。 -
oldLayout
是图像布局转换中的旧布局。 -
newLayout
是图像布局转换中的新布局。 -
subresourceRange
描述了image
中受此布局转换影响的图像子资源范围。
vkTransitionImageLayout
在执行布局转换之前,不会检查与图像关联的设备内存当前是否正在使用。应用程序必须保证,在主机执行布局转换之前,任何先前提交的读取或写入此子资源的命令都已完成。主机访问image
的内存,就像一致一样。
在主机上执行的图像布局转换不需要队列族所有权转移,因为对于此函数支持的布局,图像的物理布局在队列族之间不会变化。 |
如果设备已写入图像内存,则不会自动使其对主机可用。在调用此命令之前,必须已在设备上发布了此图像的内存屏障,其第二个同步范围包括 由于队列提交自动使主机内存对设备可见,因此在设备上使用此布局转换的结果之前,不需要内存屏障。 |
队列族所有权转移
使用 VK_SHARING_MODE_EXCLUSIVE
的 VkSharingMode 创建的资源,必须显式地将其所有权从一个队列族转移到另一个队列族,以便在不同队列族的队列上以明确定义的方式访问其内容。
特殊的队列族索引 VK_QUEUE_FAMILY_IGNORED
表示忽略队列族参数或成员。
#define VK_QUEUE_FAMILY_IGNORED (~0U)
使用外部内存与外部 API 或实例共享的资源,也必须显式地管理本地和外部队列(或外部 API 中的等效构造)之间的所有权转移,无论创建它们时指定的 VkSharingMode 是什么。
特殊的队列族索引 VK_QUEUE_FAMILY_EXTERNAL
表示资源当前 Vulkan 实例之外的任何队列,只要该队列使用与资源的 VkDevice 相同的底层设备组或物理设备,以及相同的驱动程序版本,如 VkPhysicalDeviceIDProperties::deviceUUID
和 VkPhysicalDeviceIDProperties::driverUUID
所示。
#define VK_QUEUE_FAMILY_EXTERNAL (~1U)
或等效的
#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL
特殊的队列族索引 VK_QUEUE_FAMILY_FOREIGN_EXT
表示资源当前 Vulkan 实例之外的任何队列,无论该队列的底层物理设备或驱动程序版本如何。这包括,例如,固定功能图像处理设备、媒体编解码器设备和显示设备的队列,以及所有使用与资源的 VkDevice 相同的底层设备组或物理设备和相同驱动程序版本的队列。
#define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U)
如果在不同队列族的两个队列之间使用此类资源时,正确表达了内存依赖关系,但没有定义所有权转移,则对于第二个队列族执行的任何读取访问,该资源的内容都是未定义的。
如果应用程序不需要在从一个队列族转移到另一个队列族时保持资源内容的有效性,则应该跳过所有权转移。 |
应用程序应该预期与 |
队列族所有权转移由两个不同的部分组成
-
从源队列族释放独占所有权
-
为目标队列族获取独占所有权
应用程序必须确保这些操作按正确的顺序发生,方法是在它们之间定义执行依赖关系,例如使用信号量。
释放操作用于释放缓冲区或图像子资源范围的独占所有权。释放操作通过在来自源队列族的队列上执行 缓冲区内存屏障(对于缓冲区范围)或 图像内存屏障(对于图像子资源范围)使用管线屏障命令来定义。屏障的 srcQueueFamilyIndex
参数必须是源队列族索引,并且 dstQueueFamilyIndex
参数必须是目标队列族索引。对于此类屏障,将忽略目标访问掩码,这样不会执行任何可见性操作 - 此掩码的值不影响屏障的有效性。释放操作发生在可用性操作之后。如果 dependencyFlags
不包括 VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则根据 缓冲区内存所有权转移和 图像内存所有权转移的定义,此类屏障也将忽略 dstStageMask
。
获取操作 用于获取缓冲区或图像子资源范围的独占所有权。获取操作的定义是在目标队列族中的队列上,使用管线屏障命令执行缓冲区内存屏障(对于缓冲区范围)或图像内存屏障(对于图像子资源范围)。获取操作中指定的缓冲区范围或图像子资源范围必须与之前的释放操作完全匹配。屏障的 srcQueueFamilyIndex
参数必须是源队列族索引,而 dstQueueFamilyIndex
参数必须是目标队列族索引。源访问掩码对于此类屏障将被忽略,因此不会执行可用性操作 - 此掩码的值不影响屏障的有效性。获取操作先于可见性操作发生。如果 dependencyFlags
不包含 VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR
,则 srcStageMask
对于此类屏障也会被忽略,如缓冲区内存所有权转移和图像内存所有权转移所定义。
虽然为用于释放或获取操作的内存屏障提供目标或源访问掩码并非无效,但它们没有实际效果。释放操作之后的访问结果是未定义的,因此这些访问的可见性没有实际效果。同样,在获取操作之前的写入访问将对未来的访问产生未定义的结果,因此这些写入的可用性没有实际用途。在规范的早期版本中,要求这些掩码在两侧匹配 - 但后来放宽了此要求。这些掩码应该设置为 0。 |
为确保获取和释放操作有效,释放操作必须先于获取操作发生。通常,信号量直接用于此目的,信号量在释放后发出信号,然后在获取之前等待。在引入 |
如果传输通过图像内存屏障进行,并且需要进行图像布局转换,则释放操作的内存屏障中的 oldLayout
和 newLayout
的值必须等于获取操作的内存屏障中的 oldLayout
和 newLayout
的值。虽然图像布局转换提交了两次,但它只会执行一次。以此方式指定的布局转换发生在释放操作之后,且发生在获取操作之前。
如果 srcQueueFamilyIndex
和 dstQueueFamilyIndex
的值相等,则不会执行所有权转移,并且屏障的操作就好像它们都设置为 VK_QUEUE_FAMILY_IGNORED
一样。
队列族所有权转移可能对绑定到图像子资源或缓冲区范围的所有内存执行读写访问,因此应用程序必须确保所有内存写入在执行队列族所有权转移之前都已可用。可用内存会自动对队列族释放和获取操作变得可见,并且这些操作执行的写入会自动变得可用。
一旦队列族获取了 VK_SHARING_MODE_EXCLUSIVE
资源的缓冲区范围或图像子资源范围的所有权,其内容对于其他队列族来说是未定义的,除非所有权被转移。在释放或获取操作之后,绑定到已转移缓冲区或图像子资源范围的任何其他资源部分的内容都是未定义的。
因为事件不能直接用于队列间同步,并且因为vkCmdSetEvent 没有释放操作所需的队列族索引或内存屏障参数,所以队列族所有权转移的释放和获取操作只能使用vkCmdPipelineBarrier执行。 |
当从上述为外部内存所有权转移保留的特殊队列族之一获取子资源范围的所有权时,获取操作可能会产生性能损失。在某些情况下,应用程序可以通过向获取操作的内存屏障结构的 pNext
链添加VkExternalMemoryAcquireUnmodifiedEXT结构来减少性能损失。
VkExternalMemoryAcquireUnmodifiedEXT
结构定义如下
// Provided by VK_EXT_external_memory_acquire_unmodified
typedef struct VkExternalMemoryAcquireUnmodifiedEXT {
VkStructureType sType;
const void* pNext;
VkBool32 acquireUnmodifiedMemory;
} VkExternalMemoryAcquireUnmodifiedEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
如果
acquireUnmodifiedMemory
指定为VK_TRUE
,则表示绑定到内存屏障子资源范围的资源的VkDeviceMemory的任何范围,自该资源最近一次将所有权释放给内存屏障的srcQueueFamilyIndex
指定的队列族以来,从未被修改过。如果为VK_FALSE
,则不指定任何内容。
如果应用程序使用内存屏障结构将子资源范围的所有权释放给为外部内存所有权转移保留的特殊队列族之一,稍后又使用内存屏障结构从同一队列族重新获取所有权,并且如果绑定到该资源的VkDeviceMemory的任何范围在释放操作和获取操作之间的任何时间都没有被修改过,那么应用程序应该将VkExternalMemoryAcquireUnmodifiedEXT结构添加到获取操作的内存屏障结构的 pNext
链,因为这可能会减少性能损失。
如果 acquireUnmodifiedMemory
为 VK_FALSE
,则此结构将被忽略。特别是,VK_FALSE
并不表示内存已被修改。
如果内存屏障的 srcQueueFamilyIndex
不是为外部内存所有权转移保留的特殊队列族,则此结构将被忽略。
应用程序确定内存是否在释放操作和获取操作之间被修改的方法不在 Vulkan 的范围之内。 对于任何访问资源的 Vulkan 操作,应用程序必须不要假设实现将资源的内存作为只读访问,即使对于表面上只读的操作(例如传输命令和着色器读取)也是如此。 VkExternalMemoryAcquireUnmodifiedEXT:: |
等待空闲操作
要在主机上等待给定队列的未完成队列操作完成,请调用
// Provided by VK_VERSION_1_0
VkResult vkQueueWaitIdle(
VkQueue queue);
-
queue
是要等待的队列。
vkQueueWaitIdle
等同于已将一个有效的栅栏提交给每个先前执行的接受栅栏的 队列提交命令,然后使用无限超时和设置为 VK_TRUE
的 waitAll
来使用 vkWaitForFences 等待所有这些栅栏发出信号。
要在主机上等待给定逻辑设备的所有队列的未完成队列操作完成,请调用
// Provided by VK_VERSION_1_0
VkResult vkDeviceWaitIdle(
VkDevice device);
-
device
是要空闲的逻辑设备。
vkDeviceWaitIdle
等同于为 device
拥有的所有队列调用 vkQueueWaitIdle
。
主机写入排序保证
当通过 队列提交命令 将一批命令缓冲区提交到队列时,它定义了与先前的主机操作以及提交到队列的命令缓冲区的执行的内存依赖关系。
第一个 同步范围 包括主机上 vkQueueSubmit 的执行以及主机内存模型定义的在其之前发生的任何事情。
一些系统允许不直接与主机内存模型集成的写入;这些必须由应用程序手动同步。一个例子是 x86 上的非临时存储指令;为了确保这些发生在提交之前,应用程序应调用 |
第一个 访问范围 包括所有对可映射设备内存的主机写入,这些写入可用于主机内存域。
第二个 访问范围 包括设备执行的所有内存访问。
同步和多个物理设备
如果一个逻辑设备包含多个物理设备,则栅栏、信号量和事件都仍然具有信号状态的单个实例。
当所有物理设备完成必要的队列操作时,栅栏会发出信号。
信号量等待和信号操作都包含一个设备索引,该索引是执行操作的唯一物理设备。这些索引在 VkDeviceGroupSubmitInfo 和 VkDeviceGroupBindSparseInfo 结构中提供。信号量并非由任何物理设备独占拥有。例如,一个信号量可以由一个物理设备发出信号,然后由另一个物理设备等待。
一个事件 只能 由发出信号的同一物理设备(或主机)等待。
校准时间戳
为了能够关联特定操作在不同时间域的时间线(例如,设备操作与主机操作)上发生的时间,Vulkan 允许从多个时间域查询校准的时间戳。
要从一组时间域查询校准的时间戳,请调用
// Provided by VK_KHR_calibrated_timestamps
VkResult vkGetCalibratedTimestampsKHR(
VkDevice device,
uint32_t timestampCount,
const VkCalibratedTimestampInfoKHR* pTimestampInfos,
uint64_t* pTimestamps,
uint64_t* pMaxDeviation);
或等效命令
// Provided by VK_EXT_calibrated_timestamps
VkResult vkGetCalibratedTimestampsEXT(
VkDevice device,
uint32_t timestampCount,
const VkCalibratedTimestampInfoKHR* pTimestampInfos,
uint64_t* pTimestamps,
uint64_t* pMaxDeviation);
-
device
是用于执行查询的逻辑设备。 -
timestampCount
是要查询的时间戳的数量。 -
pTimestampInfos
是指向timestampCount
VkCalibratedTimestampInfoKHR 结构数组的指针,描述应从中捕获校准时间戳的时间域。 -
pTimestamps
是指向timestampCount
个 64 位无符号整数值数组的指针,其中返回请求的校准时间戳值。 -
pMaxDeviation
是指向一个 64 位无符号整数值的指针,其中返回校准时间戳值的严格正最大偏差(以纳秒为单位)。
由于实现和平台特定原因,即使对于同一组时间域,对 |
校准的时间戳值 可以 被外推以估计未来一致的时间戳值,但是,根据时间域的性质和平台的其他属性,在足够长的时间内外推值 可能 不再足够准确以适合任何特定目的,因此期望应用程序定期重新校准时间戳。
VkCalibratedTimestampInfoKHR
结构的定义如下
// Provided by VK_KHR_calibrated_timestamps
typedef struct VkCalibratedTimestampInfoKHR {
VkStructureType sType;
const void* pNext;
VkTimeDomainKHR timeDomain;
} VkCalibratedTimestampInfoKHR;
或等效的
// Provided by VK_EXT_calibrated_timestamps
typedef VkCalibratedTimestampInfoKHR VkCalibratedTimestampInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
timeDomain
是一个 VkTimeDomainKHR 值,指定应从中返回校准时间戳值的时间域。
支持的时间域集合包括:
// Provided by VK_KHR_calibrated_timestamps
typedef enum VkTimeDomainKHR {
VK_TIME_DOMAIN_DEVICE_KHR = 0,
VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR = 1,
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR = 2,
VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR = 3,
// Provided by VK_EXT_calibrated_timestamps
VK_TIME_DOMAIN_DEVICE_EXT = VK_TIME_DOMAIN_DEVICE_KHR,
// Provided by VK_EXT_calibrated_timestamps
VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR,
// Provided by VK_EXT_calibrated_timestamps
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR,
// Provided by VK_EXT_calibrated_timestamps
VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR,
} VkTimeDomainKHR;
或等效的
// Provided by VK_EXT_calibrated_timestamps
typedef VkTimeDomainKHR VkTimeDomainEXT;
-
VK_TIME_DOMAIN_DEVICE_KHR
指定设备时间域。 此时间域中的时间戳值使用相同的单位,并且可以与使用 vkCmdWriteTimestamp 或 vkCmdWriteTimestamp2 捕获的设备时间戳值进行比较,并且被定义为根据设备的timestampPeriod
递增。 -
VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR
指定 POSIX 平台上可用的 CLOCK_MONOTONIC 时间域。 此时间域中的时间戳值以纳秒为单位,并且可以与使用 POSIX clock_gettime API 捕获的平台时间戳值进行比较,如以下示例计算所示:
支持 |
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return tv.tv_nsec + tv.tv_sec*1000000000ull;
-
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR
指定 POSIX 平台上可用的 CLOCK_MONOTONIC_RAW 时间域。此时间域中的时间戳值以纳秒为单位,并且可以与使用 POSIX clock_gettime API 捕获的平台时间戳值进行比较,如以下示例计算所示:
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC_RAW, &tv);
return tv.tv_nsec + tv.tv_sec*1000000000ull;
-
VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR
指定 Windows 上可用的性能计数器 (QPC) 时间域。 此时间域中的时间戳值与 Windows QueryPerformanceCounter API 提供的单位相同,并且可以与使用该 API 捕获的平台时间戳值进行比较,如以下示例计算所示:
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
return counter.QuadPart;