VK_KHR_acceleration_structure

更新记录
  • 2023/6/13 创建该文档

  • 2023/6/13 将 Vulkan KHR 光线追踪标准 中的 VK_KHR_acceleration_structure 内容摘录于此

  • 2023/6/13 更新 拷贝加速结构 章节

  • 2023/6/13 增加 vkCmdWriteAccelerationStructuresPropertiesKHR 章节

  • 2023/6/14 更新 vkCmdWriteAccelerationStructuresPropertiesKHR 章节

  • 2023/6/14 增加 vkCmdCopyAccelerationStructureKHR 章节

  • 2023/6/14 增加 VkCopyAccelerationStructureInfoKHR 章节

  • 2023/6/14 增加 vkCmdCopyAccelerationStructureToMemoryKHR 章节

  • 2023/6/15 更新 vkCmdCopyAccelerationStructureToMemoryKHR 章节

  • 2023/6/15 修改 获取64位加速结构设备地址 章节顺序

  • 2023/6/15 增加 VkCopyAccelerationStructureToMemoryInfoKHR 章节

  • 2023/6/15 增加 vkGetDeviceAccelerationStructureCompatibilityKHR 章节

  • 2023/6/15 增加 VkAccelerationStructureVersionInfoKHR 章节

  • 2023/6/15 增加 VkAccelerationStructureCompatibilityKHR 章节

  • 2023/6/15 修改 销毁加速结构 章节顺序

  • 2023/6/15 增加 加速结构的 Host 端操作 章节

  • 2023/6/19 更新 加速结构的 Host 端操作 章节

  • 2023/6/19 增加 vkBuildAccelerationStructuresKHR 章节

  • 2023/6/19 增加 vkCopyAccelerationStructureKHR 章节

  • 2023/6/19 增加 vkCopyAccelerationStructureToMemoryKHR 章节

  • 2023/6/19 增加 vkWriteAccelerationStructuresPropertiesKHR 章节

  • 2023/6/21 修改 VK_KHR_device_group_creationdevice扩展 修改成 instance扩展

加速结构的创建和构建

加速结构中经常能看到 创建构建 的字样,这是两个不同的概念。加速结构的创建指的是创建加速结构句柄 VkAccelerationStructureKHR ,在创建时可以不指定其内部的具体数据,可以先创建。对于加速结构的构建指的是构建加速结构内部真正的数据和结构,具体内部结构是什么形式的是驱动内部自定义的(一种可能的结构为 BVH )。

该扩展属于 device扩展

依赖如下

新添加的对象类型(句柄):

新添加的函数:

查看是否支持加速结构特性

如果使用 Vulkan 1.1 标准,可以通过调用 vkGetPhysicalDeviceFeatures2 获取加速结构特性相关信息。

// 由 Vulkan 1.1 提供
void vkGetPhysicalDeviceFeatures2(
VkPhysicalDevice                            physicalDevice,
VkPhysicalDeviceFeatures2*                  pFeatures);

如果激活了 VK_KHR_get_physical_device_properties2 扩展,可以通过 vkGetPhysicalDeviceFeatures2KHR 获取。

// 由 VK_KHR_get_physical_device_properties2 提供
void vkGetPhysicalDeviceFeatures2KHR(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceFeatures2*                  pFeatures);

对于获取设备是否支持加速结构特性,是通过将 VkPhysicalDeviceAccelerationStructureFeaturesKHR 的指针包含在 VkPhysicalDeviceFeatures2::pNext 指针链中。

// 由 Vulkan 1.1 提供
typedef struct VkPhysicalDeviceFeatures2 {
    VkStructureType             sType;
    void*                       pNext;
    VkPhysicalDeviceFeatures    features;
} VkPhysicalDeviceFeatures2;
// 由 VK_KHR_acceleration_structure 提供
typedef struct VkPhysicalDeviceAccelerationStructureFeaturesKHR {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           accelerationStructure;
    VkBool32           accelerationStructureCaptureReplay;
    VkBool32           accelerationStructureIndirectBuild;
    VkBool32           accelerationStructureHostCommands;
    VkBool32           descriptorBindingAccelerationStructureUpdateAfterBind;
} VkPhysicalDeviceAccelerationStructureFeaturesKHR;
  • accelerationStructure 描述设备是否支持加速结构特性。

  • accelerationStructureCaptureReplay 描述设备是否支持保存和重复使用加速结构的设备地址。比如用于追踪捕获和回放。

  • accelerationStructureIndirectBuild 描述设备是否支持间接加速结构构建指令。比如 vkCmdBuildAccelerationStructuresIndirectKHR

  • accelerationStructureHostCommands 描述设备是否支持 Host 端( CPU )的加速结构相关指令函数。比如 vkBuildAccelerationStructuresKHRvkCopyAccelerationStructureKHRvkCopyAccelerationStructureToMemoryKHRvkCopyMemoryToAccelerationStructureKHRvkWriteAccelerationStructuresPropertiesKHR

  • descriptorBindingAccelerationStructureUpdateAfterBind 描述设备是否支持在描述符集中已经绑定加速结构之后对加速结构进行更新。如果该特性不支持, VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT 将不能与 VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR 一起使用。

host 端还是 device

host 端一般指 CPUdevice 端一般指 GPU

例程

备注

需要开启 VK_KHR_get_physical_device_properties2 扩展

VkPhysicalDevice vk_physical_device = /*某个精挑细选的物理设备*/;

VkPhysicalDeviceAccelerationStructureFeaturesKHR vk_physical_device_acceleration_structure_features_khr = {};
vk_physical_device_acceleration_structure_features_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
vk_physical_device_acceleration_structure_features_khr.pNext = nullptr;
vk_physical_device_acceleration_structure_features_khr.accelerationStructure = VK_FALSE;
vk_physical_device_acceleration_structure_features_khr.accelerationStructureCaptureReplay = VK_FALSE;
vk_physical_device_acceleration_structure_features_khr.accelerationStructureIndirectBuild = VK_FALSE;
vk_physical_device_acceleration_structure_features_khr.accelerationStructureHostCommands = VK_FALSE;
vk_physical_device_acceleration_structure_features_khr.descriptorBindingAccelerationStructureUpdateAfterBind = VK_FALSE;

VkPhysicalDeviceFeatures2 vk_physical_device_features_2;
vk_physical_device_features_2.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
vk_physical_device_features_2.pNext = &vk_physical_device_acceleration_structure_features_khr;
vk_physical_device_features_2.features = {};

vkGetPhysicalDeviceFeatures2KHR(vk_physical_device, &vk_physical_device_features_2);

激活加速结构特性

在创建 VkDevice 时需要将要开启的特性加入到 VkDeviceCreateInfo::pNext 指针链中。

例程

VkPhysicalDevice vk_physical_device = /*某个精挑细选的物理设备*/;
VkPhysicalDeviceAccelerationStructureFeaturesKHR vk_physical_device_acceleration_structure_features_khr = /*之前通过vkGetPhysicalDeviceFeatures2KHR获取到的加速结构特性信息*/;

VkDeviceCreateInfo vk_device_create_info = {};
vk_device_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
vk_device_create_info.pNext = &vk_physical_device_acceleration_structure_features_khr;
vk_device_create_info. ...

VkDevice vk_device = VK_NULL_HANDLE;
VkResult result = vkCreateDevice(vk_physical_device, &vk_device_create_info, &vk_device);
if (result != VK_SUCCESS)
{
    /*创建失败*/
}

获取缓存的设备地址

vkGetBufferDeviceAddress

为了使得着色器可以访问缓存我们需要获取缓存的设备地址,调用如下:

// 由 VK_VERSION_1_2 提供
VkDeviceAddress vkGetBufferDeviceAddress(
    VkDevice                                    device,
    const VkBufferDeviceAddressInfo*            pInfo);

或者与之相等的函数:

vkGetBufferDeviceAddressKHR

// 由 VK_KHR_buffer_device_address 提供
VkDeviceAddress vkGetBufferDeviceAddressKHR(
    VkDevice                                    device,
    const VkBufferDeviceAddressInfo*            pInfo);
  • device 创建缓存的逻辑设备。

  • pInfo 指向 VkBufferDeviceAddressInfo 结构体指针,内部指定了要获取的目标缓存。

VkBufferDeviceAddressInfo

VkBufferDeviceAddressInfo 定义如下:

// 由 VK_VERSION_1_2 提供
typedef struct VkBufferDeviceAddressInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkBuffer           buffer;
} VkBufferDeviceAddressInfo;

或者与之相等的声明:

VkBufferDeviceAddressInfoKHR

// 由 VK_KHR_buffer_device_address 提供
typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoKHR;

正确用法

  • buffer 必须使用 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT 创建。

加速结构

加速结构是设备驱动用于光线遍历并管理场景几何体的数据结构。应用的职责是管理加速结构,包括创建、销毁、构建和更新,并在光线查询期间同步资源。

加速结构有两种:

  • 顶层加速结构( top level acceleration structures

  • 底层加速结构( bottom level acceleration structures

一个加速结构被构建的标志是对于一个目标加速结构执行了加速结构构建指令或拷贝指令。

../../_images/VulkanDocAccelerationStructure.svg

加速结构

如图为顶层加速结构和底层加速结构的关系图。

几何体

几何体指的是三角形或轴对齐包围盒。

轴对齐包围盒

也叫 AABBAxis Aligned Bounding Box )包围盒。

顶层加速结构

代表实体( instances )的集合。描述符或设备地址将顶层加速结构作为遍历的起点。

顶层加速结构通过实体可以引用任意的底层加速结构。当顶层加速结构访问底层加速结构时底层加速结构必须保持有效。

底层加速结构

用于表示几何体集合

加速结构的更新规则

Vulkan API 提供两种方式从几何体中生成加速结构:

  • 构建操作 用于构建一个加速结构

  • 更新操作 用于修改一个已经存在的加速结构

更新操作为了执行的更快更有效率在输入方面施加了一些限制。在进行更新时,应用需要提供对于加速结构完整的描述,除了实体的定义、变换矩阵、顶点和 AABB 的位置可以改变,其他的禁止发生改变并与之前的构建描述相匹配。

更明确的说,应用禁止在更新时做如下操作:

  • 将图元或实体从有效转成无效,反之亦然。

  • 更改三角形几何体的索引和顶点格式

  • 将三角形几何体的变换指针从空变成非空,反之亦然。

  • 改变加速结构中几何体或实体的数量。

  • 改变加速结构中几何体的标志位域( flags )。

  • 改变加速结构中几何体的顶点数量或图元数量。

无效的图元和实体

加速结构允许使用一个特定的输入值表示无效的图元或实体。

当三角形的每个顶点的第一个( X )分量为 NaN 时即为一个无效三角形。如果顶点的其他分量为 NaN 但是第一个分量不为 NaN 时其行为是未定义的。如果顶点格式中不存在 NaN 的话,则所有的三角形都认为是有效的。

当一个实体引用的加速结构为 0 时被认为是无效。

AABB 的最小 X 坐标为 NaN 时被认为是无效,如果其他的部分为 NaN 而第一个不是 NaN 的话其行为是未定义的。

在如上定义中 NaN 可以是任意类型的 NaN ,比如有符号的。无符号的、安静的、吵闹的或是其他种种。

安静的、吵闹的

安静的 NaN ,大概率是指 IEEE 754-2008 标准中定义的 Quiet NaN 。是指尾数最高位为 1NaN 值。 吵闹的 NaN ,大概率是指 IEEE 754-2008 标准中定义的 Signaling NaN 。是指尾数最高位为 0 ,其余低位不全为 0NaN 值。

一个无效对象对于所有的光线都被认为是不可见的,并且不应该出现在加速结构中。驱动应确保无效对象的存在不会严重降低遍历性能。

无效对象使用一个自然增涨的索引值计数,在 SPIR-V 是通过 InstanceIdPrimitiveId 体现出来。这允许场景中的对象在有效与无效之间自由的变换。不影响使用 ID 值进行索引的任何数组的布局。

对于任何有效与无效状态的转换都需要进行一个完整的加速结构重构建。如果拷贝源加速结构中有效的对象在目标加速结构中变成无效对象,反之亦然,则应用不能执行加速结构的更新。

加速结构的描述

所有的加速结构都通过 VkAccelerationStructureBuildGeometryInfoKHR 进行描述:

VkAccelerationStructureBuildGeometryInfoKHR

VkAccelerationStructureBuildGeometryInfoKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureBuildGeometryInfoKHR {
    VkStructureType                                     sType;
    const void*                                         pNext;
    VkAccelerationStructureTypeKHR                      type;
    VkBuildAccelerationStructureFlagsKHR                flags;
    VkBuildAccelerationStructureModeKHR                 mode;
    VkAccelerationStructureKHR                          srcAccelerationStructure;
    VkAccelerationStructureKHR                          dstAccelerationStructure;
    uint32_t                                            geometryCount;
    const VkAccelerationStructureGeometryKHR*           pGeometries;
    const VkAccelerationStructureGeometryKHR* const*    ppGeometries;
    VkDeviceOrHostAddressKHR                            scratchData;
} VkAccelerationStructureBuildGeometryInfoKHR;
  • sType 该结构体的类型,必须为 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • type 用于设置加速结构的构建类型。

  • flags 用于指定的加速结构的额外参数。

  • mode 用于设置要进行的操作类型。

  • srcAccelerationStructure 是用于当 modeVK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR 时其指向一个已经存在的加速结构,用于更新到 dst 加速结构中 。

  • dstAccelerationStructure 指向一个用于构建的目标加速结构。

  • geometryCount 表示要构建进入到 dstAccelerationStructure 的几何数量。

  • pGeometries 指向数量为 geometryCount 类型为 VkAccelerationStructureGeometryKHR 结构体数组。

  • ppGeometries 指向数量为 geometryCount 类型为 VkAccelerationStructureGeometryKHR 结构体 指针 数组。

  • scratchDatadevicehost 端用于构建时暂付缓存的内存地址。

暂付缓存

暂付缓存( scratch buffer ),是 Vulkan 对于内部缓存的优化。原本的内部缓存应由 Vulkan 驱动内部自身分配和管理,但是有些内部内存会经常性的更新,为了优化这一部分缓存, Vulkan 将这一部分 缓存交由用户分配管理,优化了内存使用和读写。 scratch 原本是抓挠之意,由于这部分内存时不时的要更新一下,像猫抓一样,所以叫 抓挠 缓存,实则是暂时交付给 Vulkan 驱动内部。

只有 pGeometries 或者 ppGeometries 其中之一可以设置有效指针,另外一个必须是 NULL 。有效指针所对应的数组用于描述构建加速结构的几何数据。

pGeometries 或者 ppGeometries 对应的每一个元素的索引将会作为光线遍历的几何索引。该几何索引可在光追着色器中通过内置的 RayGeometryIndexKHR 访问,并且用于在光线遍历时确定运行哪一个最近命中着色器和相交着色器。 该几何索引可以通过 OpRayQueryGetIntersectionGeometryIndexKHR 指令进行光线查询。

modeVK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHRsrcAccelerationStructuredstAccelerationStructure 对于此更新操作也许是相同的或是不同的。如果是相同的,其本身将会更新,否则。目标加速结构将会更新而不会修改源加速结构。

正确用法

  • 只有 pGeometries 或者 ppGeometries 其中之一可以设置有效指针,另外一个必须是 NULL

  • 如果 typeVK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR ,则 pGeometriesppGeometries 数组的 geometryType 必须是 VK_GEOMETRY_TYPE_INSTANCES_KHR

  • 如果 typeVK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR ,则 geometryCount 只能是 1

  • 如果 typeVK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR ,则 pGeometriesppGeometries 数组的 geometryType 必须不能是 VK_GEOMETRY_TYPE_INSTANCES_KHR

  • 如果 typeVK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR ,则 pGeometriesppGeometries 数组的 geometryType 必须相同 。

  • 如果 typeVK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR ,则 geometryCount 必须小于等于 VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxGeometryCount

  • 如果 typeVK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR ,则 pGeometriesppGeometries 数组的 geometryTypeVK_GEOMETRY_TYPE_AABBS_KHR 的话,所有数量的 AABB 对应的所有几何体必须小于等于 VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxPrimitiveCount

  • 如果 typeVK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR ,则 pGeometriesppGeometries 数组的 geometryTypeVK_GEOMETRY_TYPE_TRIANGLES_KHR 的话,所有数量的三角形对应的所有几何体必须小于等于 VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxPrimitiveCount

  • 如果 flags 包含 VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR 位域 ,就不能再包含 VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR 位域了。

VkBuildAccelerationStructureFlagBitsKHR

VkAccelerationStructureBuildGeometryInfoKHR::flags 可以设置的值如下:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkBuildAccelerationStructureFlagBitsKHR {
    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001,
    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002,
    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004,
    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008,
    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, // 由 VK_KHR_ray_tracing_position_fetch 提供
    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR = 0x00000800,
} VkBuildAccelerationStructureFlagBitsKHR;
  • VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR 表示可以更新 modeVK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR 的加速结构。

  • VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR 表示可以作为 modeVK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR 加速结构拷贝指令的数据源进行压缩。

  • VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR 表示在构建加速结构时优先考虑优化光追性能。

  • VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR 表示在构建加速结构时优先考虑优化构建时长。

  • VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR 表示最小化加速结构的暂付缓存,这背后可能会增加构建时长和光追性能。

  • VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR 表示当光线击中三角形获取顶点位置时可以使用该加速结构。

备注

VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHRVK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR 的设置可能会比正常创建花费更多的时间,并且应该在有相应需求时使用这两个特性。

VkBuildAccelerationStructureModeKHR

VkBuildAccelerationStructureModeKHR 枚举定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkBuildAccelerationStructureModeKHR {
    VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR = 0,
    VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1,
} VkBuildAccelerationStructureModeKHR;
  • VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR 表示目标加速结构将会使用用户提供的几何数据构建。

  • VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR 表示目标加速结构将会使用用户提供的源加速结构的几何数据进行更新。

VkDeviceOrHostAddressKHR

VkDeviceOrHostAddressKHR 定义的 union 联合体如下:

// 由 VK_KHR_acceleration_structure 提供
typedef union VkDeviceOrHostAddressKHR {
    VkDeviceAddress    deviceAddress;
    void*              hostAddress;
} VkDeviceOrHostAddressKHR;

备注

VkDeviceOrHostAddressKHR 是联合体 union

  • deviceAddress 表示通过 vkGetBufferDeviceAddressKHR 获取到的设备缓存地址。

  • hostAddress 表示 host 端的内存地址。

VkDeviceOrHostAddressConstKHR

VkDeviceOrHostAddressConstKHR 定义的 union 联合体如下:

// 由 VK_KHR_acceleration_structure 提供
typedef union VkDeviceOrHostAddressConstKHR {
    VkDeviceAddress    deviceAddress;
    const void*        hostAddress;
} VkDeviceOrHostAddressConstKHR;
  • deviceAddress 表示通过 vkGetBufferDeviceAddressKHR 获取到的设备缓存地址。

  • hostAddress 表示 host 端的内存地址。

备注

VkDeviceOrHostAddressConstKHR 是联合体 union 。比 VkDeviceOrHostAddressKHR 在命名上多了个 Const

VkAccelerationStructureGeometryKHR

VkAccelerationStructureGeometryKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureGeometryKHR {
    VkStructureType                           sType;
    const void*                               pNext;
    VkGeometryTypeKHR                         geometryType;
    VkAccelerationStructureGeometryDataKHR    geometry;
    VkGeometryFlagsKHR                        flags;
} VkAccelerationStructureGeometryKHR;
  • sType 该结构体的类型,必须为 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • geometryType 描述几何类型。

  • geometryVkAccelerationStructureGeometryDataKHR 联合类型,描述 geometryType 对应的数据。

  • flagsVkGeometryFlagBitsKHR 值的位域,用于描述几何体如何构建的额外参数。

正确用法

  • 目前 pNext 必须为 NULL

  • 如果 geometryTypeVK_GEOMETRY_TYPE_TRIANGLES_KHR 的话, geometrytriangles 成员必须是一个有效的 VkAccelerationStructureGeometryTrianglesDataKHR 结构数据。

  • 如果 geometryTypeVK_GEOMETRY_TYPE_AABBS_KHR 的话, geometryaabbs 成员必须是一个有效的 VkAccelerationStructureGeometryAabbsDataKHR 结构数据。

  • 如果 geometryTypeVK_GEOMETRY_TYPE_INSTANCES_KHR 的话, geometryinstances 成员必须是一个有效的 VkAccelerationStructureGeometryInstancesDataKHR 结构数据。

VkGeometryTypeKHR

几何类型通过 VkGeometryTypeKHR 指定,其定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkGeometryTypeKHR {
    VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0,
    VK_GEOMETRY_TYPE_AABBS_KHR = 1,
    VK_GEOMETRY_TYPE_INSTANCES_KHR = 2,
} VkGeometryTypeKHR;
  • VK_GEOMETRY_TYPE_TRIANGLES_KHR 表示几何类型由三角形组成。

  • VK_GEOMETRY_TYPE_AABBS_KHR 表示几何类型由轴对齐包围盒组成。

  • VK_GEOMETRY_TYPE_INSTANCES_KHR 表示几何类型由加速结构实体组成。

VkGeometryFlagBitsKHR

几何体在加速结构构架中额外参数:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkGeometryFlagBitsKHR {
    VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001,
    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002,
} VkGeometryFlagBitsKHR;
  • VK_GEOMETRY_OPAQUE_BIT_KHR 表示就算追踪时产生了一个击中组该几何体也不会去调用任意命中着色器。

  • VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR 表示驱动对于几何体上的每一个图元只会调用一次任意命中着色器。如果该标志位域没有设置,驱动可能会对该结合体调用多次任意命中着色器。

VkAccelerationStructureGeometryDataKHR

VkAccelerationStructureGeometryDataKHR 定义的 union 联合体如下:

// 由 VK_KHR_acceleration_structure 提供
typedef union VkAccelerationStructureGeometryDataKHR {
  VkAccelerationStructureGeometryTrianglesDataKHR triangles;
  VkAccelerationStructureGeometryAabbsDataKHR aabbs;
  VkAccelerationStructureGeometryInstancesDataKHR instances;
} VkAccelerationStructureGeometryDataKHR;
  • trianglesVkAccelerationStructureGeometryTrianglesDataKHR 结构数据。

  • aabbsVkAccelerationStructureGeometryAabbsDataKHR 结构数据。

  • instancesVkAccelerationStructureGeometryInstancesDataKHR 结构数据。

备注

VkAccelerationStructureGeometryDataKHR 是联合体 union

VkAccelerationStructureGeometryTrianglesDataKHR

VkAccelerationStructureGeometryTrianglesDataKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureGeometryTrianglesDataKHR {
  VkStructureType sType;
  const void* pNext;
  VkFormat vertexFormat;
  VkDeviceOrHostAddressConstKHR vertexData;
  VkDeviceSize vertexStride;
  uint32_t maxVertex;
  VkIndexType indexType;
  VkDeviceOrHostAddressConstKHR indexData;
  VkDeviceOrHostAddressConstKHR transformData;
} VkAccelerationStructureGeometryTrianglesDataKHR;
  • sType 该结构体的类型,必须为 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • vertexFormat 是顶点数据的格式。

  • vertexDatadevicehost 端包含几何顶点数据的内存地址。

  • maxVertex 是在使用该结构体构建加速结构时可以寻址的最高顶点数据索引。

  • vertexStride 点与点之间的比特跨度。

  • indexType 是索引的 VkIndexType 类型。

  • indexData 是包含索引数据的 devicehost 端内存地址。

  • transformData 是包含一个用于描述该加速结构中几何体变换数据 VkTransformMatrixKHRdevicehost 端内存地址。该数据的设置是可选的。

备注

与图形管线 VkVertexInputBindingDescription 的顶端缓存跨度最大不能超过 maxVertexInputBindingStride 不同,加速结构几何体的 vertexStride 被限制在32位值中。

正确用法

  • vertexStride 必须为 vertexFormat 最小分量比特的倍数 。

  • vertexStride 必须小于等于 \(2^{32}-1\)

  • vertexFormat 的格式特性必须包括 VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR 特性。

VkTransformMatrixKHR

VkTransformMatrixKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkTransformMatrixKHR {
  float matrix[3][4];
} VkTransformMatrixKHR;
  • matrix\(3\times4\) 行主式仿射变换矩阵 。

正确用法

  • matrix 内部的 \(3\times3\) 矩阵必须是可逆矩阵。

VkAccelerationStructureGeometryAabbsDataKHR

VkAccelerationStructureGeometryAabbsDataKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureGeometryAabbsDataKHR {
  VkStructureType sType;
  const void* pNext;
  VkDeviceOrHostAddressConstKHR data;
  VkDeviceSize stride;
} VkAccelerationStructureGeometryAabbsDataKHR
  • sType 该结构体的类型,必须为 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • datadevicehost 端包含位置数据的 VkAabbPositionsKHR 轴对齐包围盒数据内存地址。

  • stride data 条目之间的比特跨度。并且必须是 8 的倍数。

正确用法

  • stride 必须小于等于 \(2^{32}-1\)

VkAabbPositionsKHR

VkAabbPositionsKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAabbPositionsKHR {
  float minX;
  float minY;
  float minZ;
  float maxX;
  float maxY;
  float maxZ;
} VkAabbPositionsKHR;
  • minX 包围盒边界框对角的 x 位置。

  • minY 包围盒边界框对角的 y 位置。

  • minZ 包围盒边界框对角的 z 位置。

  • maxX 包围盒边界框另一对角的 x 位置。

  • maxY 包围盒边界框另一对角的 y 位置。

  • maxZ 包围盒边界框另一对角的 z 位置。

正确用法

  • minX 必须小于等于 maxX

  • minY 必须小于等于 maxY

  • minZ 必须小于等于 maxZ

VkAccelerationStructureGeometryInstancesDataKHR

VkAccelerationStructureGeometryInstancesDataKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureGeometryInstancesDataKHR {
  VkStructureType sType;
  const void* pNext;
  VkBool32 arrayOfPointers;
  VkDeviceOrHostAddressConstKHR data;
} VkAccelerationStructureGeometryInstancesDataKHR;
  • sType 该结构体的类型,必须为 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • arrayOfPointers 用于指示 data 是按照地址数组解析还是就是一个数组解析。

  • data 如果 arrayOfPointersVK_TRUE ,该 data 用于单独的 VkAccelerationStructureInstanceKHR 引用 devicehost 端数组,如果为 VK_FALSE 的话将会是 VkAccelerationStructureInstanceKHR 数组地址,并且 VkAccelerationStructureInstanceKHR 是紧密排布的。

加速结构实体 ( instances )可以构建进顶层加速结构中。每一个加速结构实体在包含所有底层加速结构的顶层加速结构中都是一个单独项。多个实体可以指向相同的底层加速结构。

加速结构实体

指的是 VkAccelerationStructureInstanceKHR 。一般在 Vulkan 光追标准中也叫 实体instances )。

VkAccelerationStructureInstanceKHR

一个加速结构实体通过 VkAccelerationStructureInstanceKHR 定义:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureInstanceKHR {
  VkTransformMatrixKHR transform;
  uint32_t instanceCustomIndex:24;
  uint32_t mask:8;
  uint32_t instanceShaderBindingTableRecordOffset:24;
  VkGeometryInstanceFlagsKHR flags:8;
  uint64_t accelerationStructureReference;
} VkAccelerationStructureInstanceKHR;
  • transform 用于描述该实体的变换。

  • instanceCustomIndex 用户自定义的 24 比特索引值。该值可通过光追着色器的内置变量 InstanceCustomIndexKHR 进行访问。

  • mask 是一个 8 比特可见性遮罩值。只有当 Cull Mask & instance.mask != 0 时实体才会被光线击中。

  • instanceShaderBindingTableRecordOffset 是一个 24 比特偏移值。用于计算命中着色器绑定表索引。

  • flags 是一个 8 比特 VkGeometryInstanceFlagBitsKHR 遮罩值引用在该实体上。

  • accelerationStructureReference 是一下两者之一。
    • vkGetAccelerationStructureDeviceAddressKHR 获取到包含数据的 device 地址。将会被用于加速结构 device 操作中。

    • 一个 VkAccelerationStructureKHR 对象。将会被用于设备加速结构 host 操作中。

C 语言标准的规范并没有定义位域的顺序,但是一般,对于现有编译器都会提供正确的结构体布局。这默认的位域模板如下:

  • instanceCustomIndexmask 将会一同占用一个 uint32_t
    • instanceCustomIndex 占用开头的 24

    • mask 占用之后的 8

  • instanceShaderBindingTableRecordOffsetflags 将会一同占用一个 uint32_t
    • instanceCustomIndex 占用开头的 24

    • mask 占用之后的 8

如果编译器没有按照此方式进行结构体内存布局,应用需要根据如上模板使用其他方式设置数值。

VkGeometryInstanceFlagBitsKHR

VkAccelerationStructureInstanceKHR::flags 用于设置实体的行为位域值如下:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkGeometryInstanceFlagBitsKHR {
  VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001,
  VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0x00000002,
  VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004,
  VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008,
  VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR,
} VkGeometryInstanceFlagBitsKHR;
  • VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR 取消实体的面剔除。

  • VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR 表示确认哪一个是正面,与之前的判断策略相反。由于是使用物体空间( object space )来判断正反面,在实体上的变换并不会影响判断结构,但是对于几何体的变换会影响判断结果。

  • VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR 表示该实体下的所有几何体都被认为是 VK_GEOMETRY_OPAQUE_BIT_KHR ,该行为可通过 SPIR-VNoOpaqueKHR 光追标志位进行覆盖。

  • VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR 表示该实体下的所有几何体都不被认为是 VK_GEOMETRY_OPAQUE_BIT_KHR ,该行为可通过 SPIR-VNoOpaqueKHR 光追标志位进行覆盖。

VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHRVK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR 这两个标志位域一定不能同时使用。

获取加速结构的构建大小

vkGetAccelerationStructureBuildSizesKHR

为了获取加速结构构建的大小,调用:

// 由 VK_KHR_acceleration_structure 提供
void vkGetAccelerationStructureBuildSizesKHR(
    VkDevice                                    device,
    VkAccelerationStructureBuildTypeKHR         buildType,
    const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo,
    const uint32_t*                             pMaxPrimitiveCounts,
    VkAccelerationStructureBuildSizesInfoKHR*   pSizeInfo);
  • device 用于创建加速结构的逻辑设备句柄。

  • buildType 指定是使用 host 端还是 device 端(或是两者兼得)上构建加速结构。

  • pBuildInfo 描述构建的参数。

  • pMaxPrimitiveCounts 是指向类型为 uint32_t 长度为 pBuildInfo->geometryCount 的数组指针。用于定义有多少图元构建进入每个几何体中。

  • pSizeInfo 返回构建加速结构时需要的大小、暂付缓存的大小。

获取加速结构的构建大小

在获取加速结构要构建的大小时,主要是通过 VkAccelerationStructureBuildGeometryInfoKHR 描述加速结构,而不像 VkImageVkBuffer 这类先创建资源句柄再获取资源要分配的大小。换而言之,加速结构在获取大小时不需要先创建完加速结构资源句柄后再获取大小。

在调用该函数时 pBuildInfosrcAccelerationStructuredstAccelerationStructuremode 成员数据会被忽略。 pBuildInfoVkDeviceOrHostAddressKHR scratchData 也将会被忽略,除非 VkAccelerationStructureGeometryTrianglesDataKHR::transformData 中的 hostAddress 成员是 NULL

使用该函数中的 VkAccelerationStructureBuildSizesInfoKHR 返回的 accelerationStructureSize 的大小创建加速结构,为了支持使用 VkAccelerationStructureBuildGeometryInfoKHRVkAccelerationStructureBuildRangeInfoKHR 数组进行任意的构建和更新,构建和更新时需要依照如下规范:

  • 构建指令是 host 端, buildType 需要是 VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR 或者 VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR

  • 构建指令是 device 端, buildType 需要是 VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR 或者 VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR

  • 对于 VkAccelerationStructureBuildGeometryInfoKHR
    • typeflags 成员需要分别与 pBuildInfo->typepBuildInfo->flags 对应相等。

    • geometryCount 需要小于等与 pBuildInfo->geometryCount

    • 对于 pGeometriesppGeometries 数组中的每一个元素,其 geometryType 成员需要与 pBuildInfo->geometryType 相等。

    • 对于 pGeometriesppGeometries 数组中的每一个元素,其 flags 成员需要与 pBuildInfo->flags 相等。

    • 对于 pGeometriesppGeometries 数组中的每一个元素,当其 geometryType 成员等于 VK_GEOMETRY_TYPE_TRIANGLES_KHR 时, geometry.trianglesvertexFormatindexType 成员需要与 pBuildInfo 中的对应成员相等。

    • 对于 pGeometriesppGeometries 数组中的每一个元素,当其 geometryType 成员等于 VK_GEOMETRY_TYPE_TRIANGLES_KHR 时, geometry.trianglesmaxVertex 成员需要与 pBuildInfo 中的对应成员相等。

    • 对于 pGeometriesppGeometries 数组中的每一个元素,当其 geometryType 成员等于 VK_GEOMETRY_TYPE_TRIANGLES_KHR 时, geometry.trianglestransformData 成员不是 NULLpBuildInfo 对应的 transformData.hostAddress 也不能是 NULL

  • 对于每一个与 VkAccelerationStructureBuildGeometryInfoKHR 对应的 VkAccelerationStructureBuildRangeInfoKHR
    • VkAccelerationStructureBuildGeometryInfoKHRprimitiveCount 成员需要小于等于对应 pMaxPrimitiveCounts 的元素。

与之相似的 updateScratchSize 在如上规范下使用 VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHRmode 的话将支持任意构建指令,并且 buildScratchSize 值在如上规范下使用 VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHRmode 的话将支持任意构建指令。

正确用法

  • 必须激活 rayTracingPipelinerayQuery 特性。

  • 如果 device 使用多物理设备创建的,则一定不能激活 bufferDeviceAddressMultiDevice 特性。

  • 如果 pBuildInfo->geometryCount 不是 0 的话, pMaxPrimitiveCounts 必须指向一个有效的类型为 uint32_t 长度为 pBuildInfo->geometryCount 的数组指针。

  • 如果 pBuildInfo->pGeometriespBuildInfo->ppGeometries 有一个 VK_GEOMETRY_TYPE_INSTANCES_KHR 类型的 geometryType 的话,每一个 pMaxPrimitiveCounts[i] 必须小于等于 VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxInstanceCount

VkAccelerationStructureBuildTypeKHR

对于 vkGetAccelerationStructureBuildSizesKHR 中的 buildType 可设值为:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkAccelerationStructureBuildTypeKHR {
    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0,
    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1,
    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2,
} VkAccelerationStructureBuildTypeKHR;
  • VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR 请求的内存将会使用 host 端进行操作。

  • VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR 请求的内存将会使用 device 端进行操作。

  • VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR 请求的内存将会同时支持使用 host 端和 device 端进行操作。

VkAccelerationStructureBuildSizesInfoKHR

VkAccelerationStructureBuildSizesInfoKHR 结构体描述了加速结构构建需求大小和暂付缓存的大小:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureBuildSizesInfoKHR {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceSize       accelerationStructureSize;
    VkDeviceSize       updateScratchSize;
    VkDeviceSize       buildScratchSize;
} VkAccelerationStructureBuildSizesInfoKHR;
  • sType 该结构体的类型,必须为 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • accelerationStructureSizeVkAccelerationStructureKHR 在构建和更新时需要的比特大小。

  • updateScratchSize 在更新时需要暂付缓存的比特大小。

  • buildScratchSize 在构建时需要暂付缓存的比特大小。

创建加速结构

vkCreateAccelerationStructureKHR

通过调用 vkCreateAccelerationStructureKHR 创建加速结构

// 由 VK_KHR_acceleration_structure 提供
VkResult vkCreateAccelerationStructureKHR(
    VkDevice                                    device,
    const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkAccelerationStructureKHR*                 pAccelerationStructure);
  • device 用于创建加速结构的逻辑设备句柄。

  • pCreateInfo 加速结构的构建信息。

  • pAllocator 分配器。

  • pAccelerationStructure 创建的目标加速结构句柄。

加速结构仅仅用于创建一个具有特定形状的物体。可以构建进入加速结构的几何数量和类型是通过 VkAccelerationStructureCreateInfoKHR 来指定。

之后往加速结构内部填入数据和绑定内存是通过调用 vkCmdBuildAccelerationStructuresKHRvkBuildAccelerationStructuresKHRvkCmdCopyAccelerationStructureKHRvkCopyAccelerationStructureKHR 函数实现的。

在将缓存输入构建加速结构指令构建加速结构时,如何构建加速结构是设备自己内部实现。

正确用法

  • 必须激活 accelerationStructure 特性。

  • 如果 VkAccelerationStructureCreateInfoKHR::deviceAddress 不是 0 的话,需要激活 accelerationStructureCaptureReplay 特性。

  • 如果 device 是从多个物理设备建立的话,需要激活 bufferDeviceAddressMultiDevice 特性。

VkAccelerationStructureCreateInfoKHR

对应调用 vkCreateAccelerationStructureKHR 时,需要设置对应的 VkAccelerationStructureCreateInfoKHR 创建信息。

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureCreateInfoKHR {
    VkStructureType                          sType;
    const void*                              pNext;
    VkAccelerationStructureCreateFlagsKHR    createFlags;
    VkBuffer                                 buffer;
    VkDeviceSize                             offset;
    VkDeviceSize                             size;
    VkAccelerationStructureTypeKHR           type;
    VkDeviceAddress                          deviceAddress;
} VkAccelerationStructureCreateInfoKHR;
  • sType 该结构体的类型,必须是 VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR

  • pNext 要么是 NULL 要么指向 VkAccelerationStructureMotionInfoNVVkOpaqueCaptureDescriptorDataCreateInfoEXT

  • createFlagsVkAccelerationStructureCreateFlagBitsKHR 的位域,用于创建加速结构时指定附加参数。

  • buffer 加速结构将会存储的目标缓存。

  • offset 对于目标缓存的起始地址的比特偏移,在目标缓存的此偏移位置之后存储加速结构。偏移值必须是 256 的倍数。

  • size 加速结构需要的大小。

  • type VkAccelerationStructureTypeKHR 枚举值,用于创建的加速结构类型。

  • deviceAddress 如果使用 accelerationStructureCaptureReplay 特性,需要该加速结构请求的设备地址。

如果 deviceAddress0 的话,表示没有指定请求地址。

如果 deviceAddress 不为 0 的话,其地址需要与 buffer 相对应。

应用应该避免在同一进程中使用应用提供的地址和设备实现提供的地址,这是为了减少 VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR 错误出现的可能性。

备注

一个预期的用法是将追踪捕获、回放工具,在使用 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT 位域创建的所有缓存上添加 VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT 位域,并且在那些 deviceAddress 不是 0 的 加速结构所对应的所有用于存储的缓存上增加 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT 位域。这也就意味着在应用还没有需要增加 VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT 位域时,工具需要对于内存分配增加 VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT 位域。 在捕获期间,工具将会保存捕获追踪到的设备地址。在回放期间,缓存将会根据原始地址创建,所以任何在追踪数据中存储的地址值将会一直处于有效状态。

驱动实现比较喜欢将这些缓存在 GPU 地址空间上进行分解,所以正常的内存分配将不会使用这些分解内存。为了避免地址空间分配冲突,应用或工具需要避免在 VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT 缓存上混合使用应用和驱动提供的地址。

应用应该使用除了 VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR 之外的 VkAccelerationStructureTypeKHR 类型来创建加速结构

备注

VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR 本意是给 API 转换层( API translation layers )使用的。 该类型可以在你创建加速结构时不清楚创建的是顶层加速结构还是底层加速结构时使用。在构建时真正的加速结构类型必须指定为 VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHRVK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR

如果加速结构将作为构建的目标,加速结构需要的大小可以通过 vkGetAccelerationStructureBuildSizesKHR 获取。如果加速结构用于压缩拷贝的话, vkCmdWriteAccelerationStructuresPropertiesKHRvkWriteAccelerationStructuresPropertiesKHR 可以用于获取需要的压缩大小。

如果加速结构用于构建 VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV 的话,其 VkAccelerationStructureCreateInfoKHR::createFlags 必须包含 VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV ,并且 VkAccelerationStructureCreateInfoKHR::pNext 中增加 VkAccelerationStructureMotionInfoNV 作为构建对象的原始数据。

VkAccelerationStructureMotionInfoNV 和 VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV

这两个属于 VK_NV_ray_tracing_motion_blur ,是 NVIDIA 的扩展,并不是 KHR 扩展,目前先忽略。

VkAccelerationStructureTypeKHR

VkAccelerationStructureCreateInfoKHR::type 用于设定加速结构的类型,支持的类型为:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkAccelerationStructureTypeKHR {
    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0,
    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1,
    VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2,
} VkAccelerationStructureTypeKHR;
  • VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR 表示包含实体(引用底层加速结构)的顶层加速结构。

  • VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR 表示包含用于求交的 AABBs 或几何数据的底层加速结构。

  • VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR 表示在加速结构创建时不知道是什么类型的,具体的类型需要在构建时确定,并且构建时必须确定是顶层加速结构还是底层加速结构。

VkAccelerationStructureCreateFlagBitsKHR

VkAccelerationStructureCreateInfoKHR::createFlags 可以设置的标志位域如下:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkAccelerationStructureCreateFlagBitsKHR {
    VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001,
} VkAccelerationStructureCreateFlagBitsKHR;
  • VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR 表示加速结构的地址可以被之后的一系列执行存储和重用。

获取64位加速结构设备地址

vkGetAccelerationStructureDeviceAddressKHR

获取 64 位的加速结构设备地址,通过调用:

// 由 VK_KHR_acceleration_structure 提供
VkDeviceAddress vkGetAccelerationStructureDeviceAddressKHR(
    VkDevice                                    device,
    const VkAccelerationStructureDeviceAddressInfoKHR* pInfo);
  • device 用于之前创建加速结构的逻辑设备句柄。

  • pInfo 指向用于设定获取目标加速结构地址的 VkAccelerationStructureDeviceAddressInfoKHR 结构体。

该函数返回的 64 位的加速结构地址,可以用于与加速结构相关的设备和着色器操作,比如光线遍历和绑定加速结构。

如果加速结构在创建时 VkAccelerationStructureCreateInfoKHR::deviceAddress 给的是有效设备地址,该函数将返回与之相同的设备地址。

如果加速结构在创建时 typeVK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR 时,该函数返回的地址在使用相同的 VkBuffer 分配的 VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR 的类型加速结构必须与其他加速度结构的相对偏移量一致。

返回的地址必须以 256 比特对齐。

VkAccelerationStructureDeviceAddressInfoKHR

相应的 VkAccelerationStructureDeviceAddressInfoKHR 定义为:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureDeviceAddressInfoKHR {
    VkStructureType               sType;
    const void*                   pNext;
    VkAccelerationStructureKHR    accelerationStructure;
} VkAccelerationStructureDeviceAddressInfoKHR;
  • sType 该结构体的类型,必须为 VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • accelerationStructure 设定要获取设备地址的目标加速结构。

销毁加速结构

vkDestroyAccelerationStructureKHR

销毁一个加速结构,通过调用:

// 由 VK_KHR_acceleration_structure 提供
void vkDestroyAccelerationStructureKHR(
    VkDevice                                    device,
    VkAccelerationStructureKHR                  accelerationStructure,
    const VkAllocationCallbacks*                pAllocator);
  • device 用于销毁加速结构的逻辑设备句柄。

  • accelerationStructure 要销毁的加速结构句柄。

  • pAllocator 指定使用 host 端的内存分配器。

构建加速结构

vkCmdBuildAccelerationStructuresKHR

构建加速结构调用 vkCmdBuildAccelerationStructuresKHR :

// 由 VK_KHR_acceleration_structure 提供
void vkCmdBuildAccelerationStructuresKHR(
    VkCommandBuffer                             commandBuffer,
    uint32_t                                    infoCount,
    const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
    const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos);
  • commandBuffer 指定在哪个指令缓存中记录指令。

  • infoCount 只是要构建的加速结构的个数。该个数为 pInfosppBuildRangeInfos 需要提供的个数。

  • pInfos 是类型为 VkAccelerationStructureBuildGeometryInfoKHR 数量为 infoCount 的数组,用于定义构建的每一个加速结构中的几何体。

  • ppBuildRangeInfos 是类型为 VkAccelerationStructureBuildRangeInfoKHR 数量为 infoCount 的数组。每一个 ppBuildRangeInfos[i] 都是指向数量为 pInfos[i].geometryCount 类型为 VkAccelerationStructureBuildRangeInfoKHR 的数组,用于动态定义 pInfos[i] 中对应的几何数据在内存中偏移。

vkCmdBuildAccelerationStructuresKHR 指令支持一次性构建多个加速结构,然而在每一个加速结构构建之间是没有隐含的顺序或同步的。

备注

这也就意味着应用不能在构建底层架结构或者实体加速结构( instance acceleration structures )的同一个 vkCmdBuildAccelerationStructuresKHR 构建指令中构建顶层加速结构。同时也不能在构建时在加速结构内存或暂付缓存上使用内存混叠。

实体加速结构

大概率是指 pInfos 中的 VkAccelerationStructureGeometryKHR* pGeometries 成员中 VkAccelerationStructureGeometryInstancesDataKHR instances 成员,用于构建实体加速结构。但在构建顶层加速结构是也会使用到 VkAccelerationStructureGeometryInstancesDataKHR instances ,此处的实体加速结构是啥并不明确,待后文看看。

内存混叠

内存混叠有点类似于 C++union 。同一段内存可以被多个资源使用,多见于临时资源的覆盖,使得一段内存可以多次重复使用。

访问 VkAccelerationStructureBuildGeometryInfoKHR::scratchData 对应的暂付缓存的设备地址必须在 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段使用 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR 访问类型进行同步。 访问 VkAccelerationStructureBuildGeometryInfoKHR::srcAccelerationStructureVkAccelerationStructureBuildGeometryInfoKHR::dstAccelerationStructure 时必须在 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段使用 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHRVK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR 访问类型进行同步较适当。

访问其他的 VkAccelerationStructureGeometryTrianglesDataKHR::vertexDataVkAccelerationStructureGeometryTrianglesDataKHR::indexDataVkAccelerationStructureGeometryTrianglesDataKHR::transformDataVkAccelerationStructureGeometryAabbsDataKHR::dataVkAccelerationStructureGeometryInstancesDataKHR::data 的输入缓存 时必须在 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段使用 VK_ACCESS_SHADER_READ_BIT 访问类型进行同步。

VkAccelerationStructureBuildRangeInfoKHR

VkAccelerationStructureBuildRangeInfoKHR 定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureBuildRangeInfoKHR {
  uint32_t primitiveCount;
  uint32_t primitiveOffset;
  uint32_t firstVertex;
  uint32_t transformOffset;
} VkAccelerationStructureBuildRangeInfoKHR;
  • primitiveCount 为对应的几何加速结构定义图元数量。

  • primitiveOffset 为图元在具体内存中的比特偏移。

  • firstVertex 为要构建的三角形几何体的第一个顶点的索引值。

  • transformOffset 为变换矩阵在具体内存中的比特偏移。

图元的数量和图元偏移将会根据不同的 VkGeometryTypeKHR 有所不同:

  • 对于类型为 VK_GEOMETRY_TYPE_TRIANGLES_KHR 的几何体, primitiveCount 是要构建的三角形数量,每个三角形被认为由三个顶点组成。
    • 如果几何体使用索引,将会从 VkAccelerationStructureGeometryTrianglesDataKHR::indexData 中使用 primitiveCount \(\times3\) 数量的索引数据,并从 primitiveOffset 偏移开始。获取顶点时,将会在索引值上加上 firstVertex 数量值。

    • 如果几何体不使用索引,将会从 VkAccelerationStructureGeometryTrianglesDataKHR::vertexData 中使用 primitiveCount \(\times3\) 数量的顶点数据,并从 primitiveOffset \(+\) VkAccelerationStructureGeometryTrianglesDataKHR::vertexStride \(\times\) firstVertex 偏移开始。

    • 如果 VkAccelerationStructureGeometryTrianglesDataKHR::transformData 不是 NULL 的话, 将会从 VkAccelerationStructureGeometryTrianglesDataKHR::transformData 中在 transformOffset 偏移之后获取一个 VkTransformMatrixKHR 结构体数据。

  • 对于类型为 VK_GEOMETRY_TYPE_AABBS_KHRprimitiveCount 是轴对齐包围盒的个数。将会从 VkAccelerationStructureGeometryAabbsDataKHR::dataprimitiveOffset 偏移之后获取 primitiveCountVkAabbPositionsKHR 结构体数据。

  • 对于类型为 VK_GEOMETRY_TYPE_INSTANCES_KHRprimitiveCount 是加速结构的个数。将会从 VkAccelerationStructureGeometryInstancesDataKHR::dataprimitiveOffset 偏移之后获取 primitiveCountVkAccelerationStructureInstanceKHR 结构体数据。

正确用法

  • 对于类型为 VK_GEOMETRY_TYPE_TRIANGLES_KHR ,如果几何体使用索引, VkAccelerationStructureGeometryTrianglesDataKHR::indexData 必须是 VkAccelerationStructureGeometryTrianglesDataKHR::indexType 元素大小的倍数。

  • 对于类型为 VK_GEOMETRY_TYPE_TRIANGLES_KHR ,如果几何体不使用索引, VkAccelerationStructureGeometryTrianglesDataKHR::vertexData 必须是 VkAccelerationStructureGeometryTrianglesDataKHR::vertexFormat 元素大小的倍数。

  • 对于类型为 VK_GEOMETRY_TYPE_TRIANGLES_KHR , 对于 VkAccelerationStructureGeometryTrianglesDataKHR::transformData 的偏移 transformOffset 必须是 16 的倍数。

  • 对于类型为 VK_GEOMETRY_TYPE_AABBS_KHR , 对于 VkAccelerationStructureGeometryAabbsDataKHR::data 的偏移 primitiveOffset 必须是 8 的倍数。

  • 对于类型为 VK_GEOMETRY_TYPE_INSTANCES_KHR , 对于 VkAccelerationStructureGeometryInstancesDataKHR::data 的偏移 primitiveOffset 必须是 16 的倍数。

拷贝加速结构

还有一个用于拷贝加速结构的命令而不更新其内容。加速结构可以进行压缩来获得更高的性能。在拷贝前,应用必须先查询加速结构的大小。

vkCmdWriteAccelerationStructuresPropertiesKHR

查询加速结构的大小调用:

// 由 VK_KHR_acceleration_structure 提供
void vkCmdWriteAccelerationStructuresPropertiesKHR(
    VkCommandBuffer                             commandBuffer,
    uint32_t                                    accelerationStructureCount,
    const VkAccelerationStructureKHR*           pAccelerationStructures,
    VkQueryType                                 queryType,
    VkQueryPool                                 queryPool,
    uint32_t                                    firstQuery);
  • commandBuffer 用于记录该指令的命令缓存。

  • accelerationStructureCount 要查询的加速结构的数量。

  • pAccelerationStructures 指向构建完成的加速结构数组。

  • queryType 其为 VkQueryType 中的值,用于管理查询池的查询类型。

  • queryPool 用于管理查询结果的查询池。

  • firstQuery 在查询池中包含 accelerationStructureCount 数量的查询结果的第一个查询索引。

访问 pAccelerationStructures 中的任何一个加速结构都需要在 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHRVK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段和 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR 访问类型进行同步。

  • 如果 queryTypeVK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR 的话,则返回的查询值就是加速结构压缩之后需要的比特数量。

  • 如果 queryTypeVK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR 的话,则返回的查询值就是加速结构序列化之后需要的比特数量。

正确用法

  • 需要激活 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure 特性

  • queryPool 创建时的 queryType 必须与 vkCmdWriteAccelerationStructuresPropertiesKHR::queryType 相匹配。

  • pAccelerationStructures 中的加速结构在必须通过 buffer 绑定到了设备内存上。

  • pAccelerationStructures 中的加速结构在调用该指令之前必须已经构建完成。

  • 如果 queryTypeVK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR 的话, pAccelerationStructures 中所有的加速结构必须根据 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR 构建的。

  • queryType 必须是 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHRVK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHRVK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHRVK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR

vkCmdCopyAccelerationStructureKHR

拷贝加速结构调用:

// 由 VK_KHR_acceleration_structure 提供
void vkCmdCopyAccelerationStructureKHR(
    VkCommandBuffer                             commandBuffer,
    const VkCopyAccelerationStructureInfoKHR*   pInfo);
  • commandBuffer 用于记录该指令的命令缓存。

  • pInfo 指向 VkCopyAccelerationStructureInfoKHR 结构体,用于定义拷贝操作。

该指令将会根据 pInfo->mode 中的模式将 pInfo->src 的加速结构拷贝至 pInfo->dst 加速结构中。

访问 pInfo->srcpInfo->dst 必须使用 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHRVK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR 访问类型,在 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHRVK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段进行同步。

正确用法

  • 需要激活 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure 特性

  • pInfo->src 中的加速结构在必须通过 buffer 绑定到了设备内存上。

  • pInfo->dst 中的加速结构在必须通过 buffer 绑定到了设备内存上。

VkCopyAccelerationStructureInfoKHR

VkCopyAccelerationStructureInfoKHR 定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkCopyAccelerationStructureInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkAccelerationStructureKHR            src;
    VkAccelerationStructureKHR            dst;
    VkCopyAccelerationStructureModeKHR    mode;
} VkCopyAccelerationStructureInfoKHR;
  • sType 该结构体的类型,必须是 VkStructureType::VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • src 拷贝的源加速结构。

  • dst 拷贝的目标加速结构。

  • mode 用于在拷贝时增加额外操作。

正确用法

  • mode 只能是 VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHRVK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR

  • src 的源加速结构在执行该指令前必须构建完成 。

  • 如果 modeVK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR 的话, src 在构建时指定 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR

  • src 中的加速结构在必须通过 buffer 绑定到了设备内存上。

  • dst 中的加速结构在必须通过 buffer 绑定到了设备内存上。

  • dst 中的加速结构在必须通过 vkBindAccelerationStructureMemoryNV 绑定到一个 VkDeviceMemory 设备内存上。该条存疑

拷贝时 mode 可能的值定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkCopyAccelerationStructureModeKHR {
    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0,
    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1,
    VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2,
    VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3,
} VkCopyAccelerationStructureModeKHR;
  • VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHRsrc 中的加速结构直接拷贝至 dst 中,其中 dst 的创建参数必须和 src 的创建参数一样。如果 src 引用了其他加速结构, dst 也需要进行相应的匹配。

  • VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHRsrc 中的加速结构压缩版本拷贝至 dst 中,其中 dst 的加速结构大小最起码需要与 src 构建之后使用 vkCmdWriteAccelerationStructuresPropertiesKHRvkWriteAccelerationStructuresPropertiesKHR 获取到的大小一致。如果 src 引用了其他加速结构, dst 也需要进行相应的匹配。

  • VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR 将加速结构序列化到一个半透明的格式中,可以在兼容实现中加载。

  • VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR 将半透明的格式反序列化到中加速结构的缓存中。

vkCmdCopyAccelerationStructureToMemoryKHR

将加速结构拷贝至设备内存中调用:

// 由 VK_KHR_acceleration_structure 提供
void vkCmdCopyAccelerationStructureToMemoryKHR(
    VkCommandBuffer                             commandBuffer,
    const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo);
  • commandBuffer 用于记录该指令的命令缓存。

  • pInfo 定义拷贝操作。

访问 pInfo->src 的加速结构时必须在 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHRVK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段使用 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR 访问类型进行同步。 访问 pInfo->dst.deviceAddress 的加速结构时必须在 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHRVK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段使用 VK_ACCESS_TRANSFER_WRITE_BIT 访问类型进行同步。

该指令与 vkCopyAccelerationStructureToMemoryKHR 函数的结果相似,只不过 vkCmdCopyAccelerationStructureToMemoryKHR 是写入 device 地址中,并且在 device 端执行而不是在 host 端。这两个指令函数的输出结果不一定每一个比特位都相同,但是在使用上 vkCmdCopyMemoryToAccelerationStructureKHRvkCopyMemoryToAccelerationStructureKHR 是一样的。

序列化数据头结构如下:

  • VK_UUID_SIZE 比特数据与 VkPhysicalDeviceIDProperties::driverUUID 相匹配。

  • VK_UUID_SIZE 比特数据使用 vkGetDeviceAccelerationStructureCompatibilityKHR 来进行兼容性对照。

  • 一个 64 位整型的总大小与 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR 查询到的相匹配。

  • 一个 64 位整型的反序列化大小最终将会传入 VkAccelerationStructureCreateInfoKHR::size

  • 一个 64 位整型表示加速结构句柄的数量。该数量与使用 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR 查询到的数量相匹配。对于底层加速结构来说是 0 ,但对于顶层加速结构来说是驱动实现相关的。句柄的数量和顺序与我们用于构建时使用的加速结构可能会不匹配。

vkGetAccelerationStructureDeviceAddressKHR 返回相匹配的句柄将会在缓存中根据数量紧凑排布。应用期望在反序列化时将句柄与应用生成的底层加速结构进行映射。将会根据 host 端的字节序列书序写入或读出缓存的序列化数据。

正确用法

  • 需要激活 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure 特性。

  • pInfo->dst.deviceAddress 必须是一个缓存绑定到设备内内存的有效设备地址。

  • pInfo->dst.deviceAddress 必须是 256 比特对齐。

  • 如果缓存指向的 pInfo->dst.deviceAddress 是非稀疏则必须绑定到一个单一的 VkDeviceMemory 对象上。

  • pInfo->src 使用到的 buffer 必须绑定到一个设备内存中。

VkCopyAccelerationStructureToMemoryInfoKHR

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkCopyAccelerationStructureToMemoryInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkAccelerationStructureKHR            src;
    VkDeviceOrHostAddressKHR              dst;
    VkCopyAccelerationStructureModeKHR    mode;
} VkCopyAccelerationStructureToMemoryInfoKHR;
  • sType 该结构体的类型,必须是 VkStructureType::VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • src 拷贝的源加速结构。

  • dst 是拷贝目标 hostdevice 内存地址。

  • mode 是拷贝时的额外参数。

正确用法

  • src 的加速结构必须在执行拷贝指令前创建完成。

  • dst 的内存大小最起码需要与使用 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR 查询类型调用 vkWriteAccelerationStructuresPropertiesKHRvkCmdWriteAccelerationStructuresPropertiesKHR 函数获取到 src 的序列化大小相同。

  • mode 只能是 VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR

vkCmdCopyMemoryToAccelerationStructureKHR

将设备内存拷贝至加速结构,调用:

// 由 VK_KHR_acceleration_structure 提供
void vkCmdCopyMemoryToAccelerationStructureKHR(
    VkCommandBuffer                             commandBuffer,
    const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo);
  • commandBuffer 用于记录该指令的命令缓存。

  • pInfo 定义拷贝操作。

访问 pInfo->dst 的加速结构时必须在 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHRVK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段使用 VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR 访问类型进行同步。 访问 pInfo->src.deviceAddress 的地址时必须在 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHRVK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR 管线阶段使用 VK_ACCESS_TRANSFER_READ_BIT 访问类型进行同步。

该指令支持使用 vkCmdCopyAccelerationStructureToMemoryKHRvkCopyAccelerationStructureToMemoryKHR 拷贝的目标内存地址。

该指令的的反序列化将会作为 vkCmdCopyAccelerationStructureToMemoryKHR 输入。

正确用法

  • 需要激活 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure 特性。

  • pInfo->src.deviceAddress 必须是已经绑定到设备内存的缓存地址。

  • pInfo->src.deviceAddress 必须是 256 比特对齐。

  • 如果缓存指向的 pInfo->src.deviceAddress 是非稀疏则必须绑定到一个单一的 VkDeviceMemory 对象上。

  • pInfo->dst 使用到的 buffer 必须绑定到一个设备内存中。

VkCopyMemoryToAccelerationStructureInfoKHR

VkCopyMemoryToAccelerationStructureInfoKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkCopyMemoryToAccelerationStructureInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkDeviceOrHostAddressConstKHR         src;
    VkAccelerationStructureKHR            dst;
    VkCopyAccelerationStructureModeKHR    mode;
} VkCopyMemoryToAccelerationStructureInfoKHR;
  • sType 该结构体的类型,必须是 VkStructureType::VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • src 拷贝的源 hostdevice 内存地址。

  • dst 是拷贝目标加速结构。

  • mode 是拷贝时的额外参数。

正确用法

  • src 的内存指针必须包含之前使用 vkCmdCopyAccelerationStructureToMemoryKHR 获取的序列化数据。可以用该函数将加速结构进行数据重定位移动。

  • mode 只能是 VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR

  • src 中的数据必须与 vkGetDeviceAccelerationStructureCompatibilityKHR 返回的目标物理设备有兼容的格式。

  • dst 创建的大小需要大于等于 src 序列化的大小。

vkGetDeviceAccelerationStructureCompatibilityKHR

为了检查序列化的加速结构是否与当前设备兼容:

// 由 VK_KHR_acceleration_structure 提供
void vkGetDeviceAccelerationStructureCompatibilityKHR(
    VkDevice                                    device,
    const VkAccelerationStructureVersionInfoKHR* pVersionInfo,
    VkAccelerationStructureCompatibilityKHR*    pCompatibility);
  • device 用于检查版本的设备。

  • pVersionInfo 用于设置检查版本的信息。

  • pCompatibility 用于返回兼容性信息。

正确用法

  • 需要激活 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure 特性。

VkAccelerationStructureVersionInfoKHR

VkAccelerationStructureVersionInfoKHR 结构体定义如下:

// 由 VK_KHR_acceleration_structure 提供
typedef struct VkAccelerationStructureVersionInfoKHR {
    VkStructureType    sType;
    const void*        pNext;
    const uint8_t*     pVersionData;
} VkAccelerationStructureVersionInfoKHR;
  • sType 该结构体的类型,必须是 VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR

  • pNext 要么是 NULL 要么指向其他结构体来扩展该结构体。

  • pVersionData 指向 vkCmdCopyAccelerationStructureToMemoryKHR 中定义的加速结构版本头。

备注

pVersionData 指向一个 \(2\times VK\_UUID\_SIZE\)uint8_t 的数组,而不是两个 VK_UUID_SIZE 数组。因为此成员的预期用例将指向内存中加载先前序列化的加速结构(通过vkCmdCopyAccelerationStructureToMemoryKHR或vkCopyAcceleration StructureToMemory KHR)的头部。使用数组将需要 UUID 的额外拷贝。不知所云

正确用法

  • pVersionData 必须是指向 \(2\times VK\_UUID\_SIZE\)uint8_t 的数组。

VkAccelerationStructureCompatibilityKHR

pCompatibility 可能的返回值如下:

// 由 VK_KHR_acceleration_structure 提供
typedef enum VkAccelerationStructureCompatibilityKHR {
    VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0,
    VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1,
} VkAccelerationStructureCompatibilityKHR;
  • VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR 表示 pVersionData 的加速结构版本与 device 兼容。

  • VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR 表示 pVersionData 的加速结构版本与 device 不兼容。

加速结构的 Host 端操作

如果驱动支持 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructureHostCommands 特性的话,这说明对于加速结构支持在 Host 端进行操作。相关 Host 端操作函数与 Device 端操作函数对应如下:

  • vkBuildAccelerationStructuresKHR 对应 vkCmdBuildAccelerationStructuresKHR

  • vkCopyAccelerationStructureKHR 对应 vkCmdCopyAccelerationStructureKHR

  • vkCopyAccelerationStructureToMemoryKHR 对应 vkCmdCopyAccelerationStructureToMemoryKHR

  • vkCopyMemoryToAccelerationStructureKHR 对应 vkCmdCopyMemoryToAccelerationStructureKHR

  • vkWriteAccelerationStructuresPropertiesKHR 对应 vkCmdWriteAccelerationStructuresPropertiesKHR

Host 端操作函数与 Device 端操作函数在功能上是等价的,只不过是在 Host 端进行操作,而不是插入到命令缓存中( command buffers )。

所有 Host 端的加速结构必须将内存绑定到 Host 端可访问的内存上,并且加速结构构建时的所有输入数据必须使用 Host 端内存而不是 Device 端数据。当时用 Host 端的函数时不需要应用将加速结构的内存映射出来。

备注

vkBuildAccelerationStructuresKHRvkCmdBuildAccelerationStructuresKHR 也许会使用不同的算法,然而并没有要求这两个函数的结果需要完全相同。这两个函数可能会分别建立各自完全不同的内存或遍历性能,但是应该尽可能地尽量做到相似。

除了这些细节之外,HostDevice 操作是可互换兼容的。比如可以使用 vkBuildAccelerationStructuresKHR 构建一个加速结构,之后可以使用 vkCmdCopyAccelerationStructureKHR 将其进行压缩,并且使用 vkCopyAccelerationStructureToMemoryKHR 将加速结构进行序列化。

备注

为了高效执行,由于驱动可能在指令执行期间反复的读写加速结构内存,所以操作这个加速结构的内存需要总是绑定到 host cached 内存上( VK_MEMORY_PROPERTY_HOST_CACHED_BIT )。

vkBuildAccelerationStructuresKHR

Host 端构建一个加速结构调用:

// 由 VK_KHR_acceleration_structure 提供
VkResult vkBuildAccelerationStructuresKHR(
    VkDevice                                    device,
    VkDeferredOperationKHR                      deferredOperation,
    uint32_t                                    infoCount,
    const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
    const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos);
  • device 表示构建加速结构对应的 VkDevice

  • deferredOperation 是一个可选的 VkDeferredOperationKHR 句柄,为该指令申请延迟操作。

  • infoCount 表示要构建的加速结构数量。并表示 pInfosppBuildRangeInfos 需要提供的数量。

  • pInfos 指向数量为 infoCount 类型为 VkAccelerationStructureBuildGeometryInfoKHR 结构体的数组,用于定义每一个要构建的加速结构。

  • ppBuildRangeInfos 指向数量为 infoCount 类型为 VkAccelerationStructureBuildRangeInfoKHR 结构体指针数组。,每一个 ppBuildRangeInfos[i] 都指向一个数量为 pInfos[i].geometryCount 类型为 VkAccelerationStructureBuildRangeInfoKHR 的结构体数组,用于对应 pInfos[i] 中几何数句的动态内存偏移。

该函数的工作和 vkCmdBuildAccelerationStructuresKHR 函数一致,只不过执行在 Host 端上。

vkBuildAccelerationStructuresKHR 支持一次性构建多个加速结构,然而构建与构建之间没有内置的顺序和同步。

备注

这也就意味着不能通过 vkBuildAccelerationStructuresKHR 函数调用同时构建底层加速结构和顶层加速结构。同样也不允许使用任何加速结构或暂付缓存的内存混叠。

vkCopyAccelerationStructureKHR

Host 端拷贝和压缩加速结构,调用:

// 由 VK_KHR_acceleration_structure 提供
VkResult vkCopyAccelerationStructureKHR(
    VkDevice                                    device,
    VkDeferredOperationKHR                      deferredOperation,
    const VkCopyAccelerationStructureInfoKHR*   pInfo);
  • device 表示构建加速结构对应的 VkDevice

  • deferredOperation 是一个可选的 VkDeferredOperationKHR 句柄,为该指令申请延迟操作。

  • pInfo 指向用于定义拷贝操作的 VkCopyAccelerationStructureInfoKHR 结构体。

该函数的工作和 vkCmdCopyAccelerationStructureKHR 函数一致,只不过执行在 Host 端上。

正确用法

  • 需要激活 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructureHostCommands 特性。

  • 如果 deferredOperation 不是 VK_NULL_HANDLE 的话,其必须是一个有效的 VkDeferredOperationKHR 句柄。

  • 任何与 deferredOperation 相关的前操作都需要完成结束。

  • 用于 pInfo->srcbuffer 必须绑定到 Host 端可访问的内存上。

  • 用于 pInfo->dstbuffer 必须绑定到 Host 端可访问的内存上。

  • 用于 pInfo->srcbuffer 必须绑定到没有分配多实体的内存上。

  • 用于 pInfo->dstbuffer 必须绑定到没有分配多实体的内存上。

vkCopyMemoryToAccelerationStructureKHR

Host 端可访问的内存拷贝到加速结构中,调用:

// 由 VK_KHR_acceleration_structure 提供
VkResult vkCopyMemoryToAccelerationStructureKHR(
    VkDevice                                    device,
    VkDeferredOperationKHR                      deferredOperation,
    const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo);
  • device 表示构建加速结构对应的 VkDevice ,与 pInfo->dst 的设备相同。

  • deferredOperation 是一个可选的 VkDeferredOperationKHR 句柄,为该指令申请延迟操作。

  • pInfo 指向用于定义拷贝操作的 VkCopyMemoryToAccelerationStructureInfoKHR 结构体。

该函数的工作和 vkCmdCopyMemoryToAccelerationStructureKHR 函数一致,只不过执行在 Host 端上。

该函数支持使用 vkCmdCopyAccelerationStructureToMemoryKHRvkCopyAccelerationStructureToMemoryKHR 的加速结构内存。

正确用法

  • 需要激活 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructureHostCommands 特性。

  • 如果 deferredOperation 不是 VK_NULL_HANDLE 的话,其必须是一个有效的 VkDeferredOperationKHR 句柄。

  • 任何与 deferredOperation 相关的前操作都需要完成结束。

  • 用于 pInfo->src.hostAddress 必须是一个有效的 Host 端指针。

  • 用于 pInfo->dstbuffer 必须绑定到 Host 端可访问的内存上。

  • 用于 pInfo->src.hostAddress 必须 16 比特对齐。

  • 用于 pInfo->dstbuffer 必须绑定到没有分配多实体的内存上。

vkCopyAccelerationStructureToMemoryKHR

将加速结构拷贝至 Host 端可访问的内存上,调用:

// 由 VK_KHR_acceleration_structure 提供
VkResult vkCopyAccelerationStructureToMemoryKHR(
    VkDevice                                    device,
    VkDeferredOperationKHR                      deferredOperation,
    const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo);
  • device 表示构建加速结构对应的 VkDevice ,与 pInfo->src 的设备相同。

  • deferredOperation 是一个可选的 VkDeferredOperationKHR 句柄,为该指令申请延迟操作。

  • pInfo 指向用于定义拷贝操作的 VkCopyAccelerationStructureToMemoryInfoKHR 结构体。

该函数的工作和 vkCmdCopyAccelerationStructureToMemoryKHR 函数一致,只不过执行在 Host 端上。

该函数与 vkCmdCopyAccelerationStructureToMemoryKHR 结果相同,只不过直接将结果写入 Host 端指针指向的内存上,并执行在 Host 端上而不是 Device 端。每次输出的结果并不一定每一个比特都相等,但都可以被 vkCmdCopyMemoryToAccelerationStructureKHRvkCopyMemoryToAccelerationStructureKHR 使用。

正确用法

  • 需要激活 VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructureHostCommands 特性。

  • 如果 deferredOperation 不是 VK_NULL_HANDLE 的话,其必须是一个有效的 VkDeferredOperationKHR 句柄。

  • 任何与 deferredOperation 相关的前操作都需要完成结束。

  • 用于 pInfo->srcbuffer 必须绑定到 Host 端可访问的内存上。

  • 用于 pInfo->dst.hostAddress 必须是有效的 Host 指针。

  • 用于 pInfo->dst.hostAddress 必须 16 比特对齐。

  • 用于 pInfo->srcbuffer 必须绑定到没有分配多实体的内存上。

vkWriteAccelerationStructuresPropertiesKHR

Host 端查询加速结构大小,调用:

// Provided by VK_KHR_acceleration_structure
VkResult vkWriteAccelerationStructuresPropertiesKHR(
    VkDevice                                    device,
    uint32_t                                    accelerationStructureCount,
    const VkAccelerationStructureKHR*           pAccelerationStructures,
    VkQueryType                                 queryType,
    size_t                                      dataSize,
    void*                                       pData,
    size_t                                      stride);
  • device 表示拥有 pAccelerationStructures 加速结构对应的 VkDevice

  • accelerationStructureCount 表示要查询的加速结构的数量。

  • pAccelerationStructures 用于指向之前构建的加速结构数组。

  • queryTypeVkQueryType 值用于设置查询类型。

  • dataSizepData 中数据的比特大小。

  • pData 指向用户分配的缓存用于写入结果。

  • stride 指向这是写入的每个结果之间的跨度。

该函数的工作和 vkCmdWriteAccelerationStructuresPropertiesKHR 函数一致,只不过执行在 Host 端上。