原子操作

本章的目的是帮助用户理解 Vulkan 为原子操作公开的各种特性。

原子操作的变体

为了更好地理解不同的扩展,首先了解公开的各种类型的原子操作非常重要。

  • 类型

    • float

    • int

  • 宽度

    • 16 位

    • 32 位

    • 64 位

  • 操作

    • 加载

    • 存储

    • 交换

    • 最小值

    • 最大值

    • 等等。

  • 存储类

    • StorageBufferUniform (缓冲区)

    • Workgroup (共享内存)

    • Image (图像或稀疏图像)

基线支持

在 Vulkan 1.0 中,没有扩展的情况下,应用程序可以使用 32 位 int 类型进行原子操作。这可以用于所有支持的 SPIR-V 操作(加载、存储、交换等)。SPIR-V 包含一些受 Kernel 功能保护的原子操作,目前在 Vulkan 中不允许使用。

原子计数器

虽然 GLSL 和 SPIR-V 都支持使用原子计数器,但 Vulkan 公开使用 AtomicCounter 存储类所需的 AtomicStorage SPIR-V 功能。最终决定应用程序只需使用 OpAtomicIAddOpAtomicISub,值为 1 即可达到相同的效果。

扩展原子操作支持

当前公开额外原子操作支持的扩展有

下面将更详细地解释每个扩展。

VK_KHR_shader_atomic_int64

在 Vulkan 1.2 中升级为核心功能

此扩展允许对 缓冲区共享内存 进行 64 位 int 原子操作。如果声明了 Int64Atomics SPIR-V 功能,则所有支持的 SPIR-V 操作都可以与 64 位 int 一起使用。

两个特性位 shaderBufferInt64AtomicsshaderSharedInt64Atomics 用于查询支持 64 位 int 原子操作的存储类。

  • shaderBufferInt64Atomics - 缓冲区

  • shaderSharedInt64Atomics - 共享内存

如果使用 Vulkan 1.2+ 或公开了该扩展,则始终保证支持 shaderBufferInt64Atomics

VK_EXT_shader_image_atomic_int64

此扩展允许对 图像稀疏图像 进行 64 位 int 原子操作。如果声明了 Int64AtomicsInt64ImageEXT SPIR-V 功能,则所有支持的 SPIR-V 操作都可以在图像上使用 64 位 int

图像与稀疏图像支持

此扩展公开了 shaderImageInt64AtomicssparseImageInt64Atomics 特性位。sparseImage* 特性是一个附加特性位,只有在启用了 shaderImage* 位时才允许使用。有些硬件很难对带有 稀疏资源 的图像进行原子操作,因此将原子特性分开,以允许 稀疏图像 作为实现可以公开的附加特性。

VK_EXT_shader_atomic_float

此扩展允许对 缓冲区共享内存图像稀疏图像 进行 float 原子操作。此扩展仅支持 float 类型的一小部分操作。

该扩展列出了许多特性位。一种对其进行分组的方法是按照 *Float*Atomics*Float*AtomicAdd 分组

  • *Float*Atomics 特性允许对 float 类型使用 OpAtomicStoreOpAtomicLoadOpAtomicExchange

    • 请注意,OpAtomicCompareExchange “交换” 操作不包括在内,因为 SPIR-V 规范仅允许其使用 int 类型。

  • *Float*AtomicAdd 特性允许使用两个扩展的 SPIR-V 操作 AtomicFloat32AddEXTAtomicFloat64AddEXT

从这里开始,其余的特性排列可以分为 32 位 float 支持组

  • shaderBufferFloat32* - 缓冲区

  • shaderSharedFloat32* - 共享内存

  • shaderImageFloat32* - 图像

  • sparseImageFloat32* - 稀疏图像

64 位 float 支持

  • shaderBufferFloat64* - 缓冲区

  • shaderSharedFloat64* - 共享内存

OpenGLES OES_shader_image_atomic 允许对 r32f 使用 imageAtomicExchange 进行原子操作。对于移植,应用程序将需要检查 shaderImageFloat32Atomics 支持,以便在 Vulkan 中执行相同的操作。

VK_EXT_shader_atomic_float2

此扩展添加了 VK_EXT_shader_atomic_float 中缺失的 2 个额外功能集。

首先,它为缓冲区共享内存添加了 16 位浮点数,其方式与上面 VK_EXT_shader_atomic_float 中的方式相同。

  • shaderBufferFloat16* - 缓冲区

  • shaderSharedFloat16* - 共享内存

其次,它为 minmax 原子操作 (OpAtomicFMinEXTOpAtomicFMaxEXT) 添加了 float 支持。

对于 16 位浮点数 支持(具有 AtomicFloat16MinMaxEXT 功能):

  • shaderBufferFloat16AtomicMinMax - 缓冲区

  • shaderSharedFloat16AtomicMinMax - 共享内存

对于 32 位浮点数 支持(具有 AtomicFloat32MinMaxEXT 功能):

  • shaderBufferFloat32AtomicMinMax - 缓冲区

  • shaderSharedFloat32AtomicMinMax - 共享内存

  • shaderImageFloat32AtomicMinMax - 图像

  • sparseImageFloat32AtomicMinMax - 稀疏图像

对于 64 位浮点数 支持(具有 AtomicFloat64MinMaxEXT 功能):

  • shaderBufferFloat64AtomicMinMax - 缓冲区

  • shaderSharedFloat64AtomicMinMax - 共享内存