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_creation
将device扩展
修改成instance扩展
加速结构的创建和构建
加速结构中经常能看到 创建
和 构建
的字样,这是两个不同的概念。加速结构的创建指的是创建加速结构句柄 VkAccelerationStructureKHR
,在创建时可以不指定其内部的具体数据,可以先创建。对于加速结构的构建指的是构建加速结构内部真正的数据和结构,具体内部结构是什么形式的是驱动内部自定义的(一种可能的结构为 BVH
)。
该扩展属于 device扩展。
依赖如下
Vulkan 1.1
- VK_EXT_descriptor_indexing device扩展 在Vulkan 1.2中被纳入核心 依赖如下
VK_KHR_get_physical_device_properties2 instance扩展 在Vulkan 1.1中被纳入核心
- VK_KHR_maintenance3 device扩展 在Vulkan 1.1中被纳入核心 依赖如下
VK_KHR_get_physical_device_properties2 instance扩展 在Vulkan 1.1中被纳入核心
- VK_KHR_buffer_device_address device扩展 在Vulkan 1.2中被纳入核心 依赖如下
VK_KHR_get_physical_device_properties2 instance扩展 在Vulkan 1.1中被纳入核心
- VK_KHR_device_group device扩展 在Vulkan 1.1中被纳入核心 依赖如下
VK_KHR_device_group_creation instance扩展 在Vulkan 1.1中被纳入核心
VK_KHR_deferred_host_operations 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
)的加速结构相关指令函数。比如vkBuildAccelerationStructuresKHR
,vkCopyAccelerationStructureKHR
,vkCopyAccelerationStructureToMemoryKHR
,vkCopyMemoryToAccelerationStructureKHR
,vkWriteAccelerationStructuresPropertiesKHR
。descriptorBindingAccelerationStructureUpdateAfterBind 描述设备是否支持在描述符集中已经绑定加速结构之后对加速结构进行更新。如果该特性不支持,
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT
将不能与VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR
一起使用。
host
端还是 device
端
host
端一般指 CPU
。 device
端一般指 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
)
一个加速结构被构建的标志是对于一个目标加速结构执行了加速结构构建指令或拷贝指令。
如图为顶层加速结构和底层加速结构的关系图。
几何体¶
几何体指的是三角形或轴对齐包围盒。
轴对齐包围盒
也叫 AABB
( Axis 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
。是指尾数最高位为 1
的 NaN
值。
吵闹的 NaN
,大概率是指 IEEE 754-2008
标准中定义的 Signaling NaN
。是指尾数最高位为 0
,其余低位不全为 0
的 NaN
值。
一个无效对象对于所有的光线都被认为是不可见的,并且不应该出现在加速结构中。驱动应确保无效对象的存在不会严重降低遍历性能。
无效对象使用一个自然增涨的索引值计数,在 SPIR-V
是通过 InstanceId
和 PrimitiveId
体现出来。这允许场景中的对象在有效与无效之间自由的变换。不影响使用 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 是用于当
mode
为VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR
时其指向一个已经存在的加速结构,用于更新到dst
加速结构中 。dstAccelerationStructure 指向一个用于构建的目标加速结构。
geometryCount 表示要构建进入到
dstAccelerationStructure
的几何数量。pGeometries 指向数量为
geometryCount
类型为VkAccelerationStructureGeometryKHR
结构体数组。ppGeometries 指向数量为
geometryCount
类型为VkAccelerationStructureGeometryKHR
结构体 指针 数组。scratchData 是
device
或host
端用于构建时暂付缓存的内存地址。
暂付缓存
暂付缓存( scratch buffer
),是 Vulkan
对于内部缓存的优化。原本的内部缓存应由 Vulkan
驱动内部自身分配和管理,但是有些内部内存会经常性的更新,为了优化这一部分缓存, Vulkan
将这一部分
缓存交由用户分配管理,优化了内存使用和读写。 scratch
原本是抓挠之意,由于这部分内存时不时的要更新一下,像猫抓一样,所以叫 抓挠
缓存,实则是暂时交付给 Vulkan
驱动内部。
只有 pGeometries
或者 ppGeometries
其中之一可以设置有效指针,另外一个必须是 NULL
。有效指针所对应的数组用于描述构建加速结构的几何数据。
pGeometries
或者ppGeometries
对应的每一个元素的索引将会作为光线遍历的几何索引。该几何索引可在光追着色器中通过内置的RayGeometryIndexKHR
访问,并且用于在光线遍历时确定运行哪一个最近命中着色器和相交着色器。 该几何索引可以通过OpRayQueryGetIntersectionGeometryIndexKHR
指令进行光线查询。
当 mode
是 VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR
时 srcAccelerationStructure
和 dstAccelerationStructure
对于此更新操作也许是相同的或是不同的。如果是相同的,其本身将会更新,否则。目标加速结构将会更新而不会修改源加速结构。
正确用法
只有
pGeometries
或者ppGeometries
其中之一可以设置有效指针,另外一个必须是NULL
。如果
type
是VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR
,则pGeometries
或ppGeometries
数组的geometryType
必须是VK_GEOMETRY_TYPE_INSTANCES_KHR
。如果
type
是VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR
,则geometryCount
只能是1
。如果
type
是VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR
,则pGeometries
或ppGeometries
数组的geometryType
必须不能是VK_GEOMETRY_TYPE_INSTANCES_KHR
。如果
type
是VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR
,则pGeometries
或ppGeometries
数组的geometryType
必须相同 。如果
type
是VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR
,则geometryCount
必须小于等于VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxGeometryCount
。如果
type
是VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR
,则pGeometries
或ppGeometries
数组的geometryType
是VK_GEOMETRY_TYPE_AABBS_KHR
的话,所有数量的AABB
对应的所有几何体必须小于等于VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxPrimitiveCount
。如果
type
是VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR
,则pGeometries
或ppGeometries
数组的geometryType
是VK_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 表示可以更新
mode
为VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR
的加速结构。VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR 表示可以作为
mode
为VK_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_KHR
和 VK_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 描述几何类型。
geometry 为
VkAccelerationStructureGeometryDataKHR
联合类型,描述geometryType
对应的数据。flags 是
VkGeometryFlagBitsKHR
值的位域,用于描述几何体如何构建的额外参数。
正确用法
目前
pNext
必须为NULL
。如果
geometryType
为VK_GEOMETRY_TYPE_TRIANGLES_KHR
的话,geometry
的triangles
成员必须是一个有效的VkAccelerationStructureGeometryTrianglesDataKHR
结构数据。如果
geometryType
为VK_GEOMETRY_TYPE_AABBS_KHR
的话,geometry
的aabbs
成员必须是一个有效的VkAccelerationStructureGeometryAabbsDataKHR
结构数据。如果
geometryType
为VK_GEOMETRY_TYPE_INSTANCES_KHR
的话,geometry
的instances
成员必须是一个有效的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;
triangles 是
VkAccelerationStructureGeometryTrianglesDataKHR
结构数据。aabbs 是
VkAccelerationStructureGeometryAabbsDataKHR
结构数据。instances 是
VkAccelerationStructureGeometryInstancesDataKHR
结构数据。
备注
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 是顶点数据的格式。
vertexData 是
device
或host
端包含几何顶点数据的内存地址。maxVertex 是在使用该结构体构建加速结构时可以寻址的最高顶点数据索引。
vertexStride 点与点之间的比特跨度。
indexType 是索引的
VkIndexType
类型。indexData 是包含索引数据的
device
或host
端内存地址。transformData 是包含一个用于描述该加速结构中几何体变换数据
VkTransformMatrixKHR
的device
或host
端内存地址。该数据的设置是可选的。
备注
与图形管线 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
要么指向其他结构体来扩展该结构体。data 是
device
或host
端包含位置数据的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 如果
arrayOfPointers
为VK_TRUE
,该data
用于单独的VkAccelerationStructureInstanceKHR
引用device
或host
端数组,如果为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
语言标准的规范并没有定义位域的顺序,但是一般,对于现有编译器都会提供正确的结构体布局。这默认的位域模板如下:
instanceCustomIndex
和mask
将会一同占用一个uint32_t
。instanceCustomIndex
占用开头的24
位mask
占用之后的8
位
instanceShaderBindingTableRecordOffset
和flags
将会一同占用一个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-V
的NoOpaqueKHR
光追标志位进行覆盖。VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR 表示该实体下的所有几何体都不被认为是
VK_GEOMETRY_OPAQUE_BIT_KHR
,该行为可通过SPIR-V
的NoOpaqueKHR
光追标志位进行覆盖。
VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR
和 VK_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
描述加速结构,而不像 VkImage
和 VkBuffer
这类先创建资源句柄再获取资源要分配的大小。换而言之,加速结构在获取大小时不需要先创建完加速结构资源句柄后再获取大小。
在调用该函数时 pBuildInfo
的 srcAccelerationStructure
、 dstAccelerationStructure
和 mode
成员数据会被忽略。 pBuildInfo
中 VkDeviceOrHostAddressKHR scratchData
也将会被忽略,除非 VkAccelerationStructureGeometryTrianglesDataKHR::transformData
中的 hostAddress
成员是 NULL
。
使用该函数中的 VkAccelerationStructureBuildSizesInfoKHR
返回的 accelerationStructureSize
的大小创建加速结构,为了支持使用 VkAccelerationStructureBuildGeometryInfoKHR
和 VkAccelerationStructureBuildRangeInfoKHR
数组进行任意的构建和更新,构建和更新时需要依照如下规范:
构建指令是
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
: 其
type
和flags
成员需要分别与pBuildInfo->type
和pBuildInfo->flags
对应相等。geometryCount
需要小于等与pBuildInfo->geometryCount
。对于
pGeometries
或ppGeometries
数组中的每一个元素,其geometryType
成员需要与pBuildInfo->geometryType
相等。对于
pGeometries
或ppGeometries
数组中的每一个元素,其flags
成员需要与pBuildInfo->flags
相等。对于
pGeometries
或ppGeometries
数组中的每一个元素,当其geometryType
成员等于VK_GEOMETRY_TYPE_TRIANGLES_KHR
时,geometry.triangles
的vertexFormat
和indexType
成员需要与pBuildInfo
中的对应成员相等。对于
pGeometries
或ppGeometries
数组中的每一个元素,当其geometryType
成员等于VK_GEOMETRY_TYPE_TRIANGLES_KHR
时,geometry.triangles
的maxVertex
成员需要与pBuildInfo
中的对应成员相等。对于
pGeometries
或ppGeometries
数组中的每一个元素,当其geometryType
成员等于VK_GEOMETRY_TYPE_TRIANGLES_KHR
时,geometry.triangles
的transformData
成员不是NULL
,pBuildInfo
对应的transformData.hostAddress
也不能是NULL
。
- 对于
- 对于每一个与
VkAccelerationStructureBuildGeometryInfoKHR
对应的VkAccelerationStructureBuildRangeInfoKHR
: 其
VkAccelerationStructureBuildGeometryInfoKHR
的primitiveCount
成员需要小于等于对应pMaxPrimitiveCounts
的元素。
- 对于每一个与
与之相似的 updateScratchSize
在如上规范下使用 VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR
的 mode
的话将支持任意构建指令,并且 buildScratchSize
值在如上规范下使用 VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR
的 mode
的话将支持任意构建指令。
正确用法
必须激活
rayTracingPipeline
或rayQuery
特性。如果
device
使用多物理设备创建的,则一定不能激活bufferDeviceAddressMultiDevice
特性。如果
pBuildInfo->geometryCount
不是0
的话,pMaxPrimitiveCounts
必须指向一个有效的类型为uint32_t
长度为pBuildInfo->geometryCount
的数组指针。如果
pBuildInfo->pGeometries
或pBuildInfo->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
要么指向其他结构体来扩展该结构体。accelerationStructureSize 为
VkAccelerationStructureKHR
在构建和更新时需要的比特大小。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
来指定。
之后往加速结构内部填入数据和绑定内存是通过调用 vkCmdBuildAccelerationStructuresKHR
、 vkBuildAccelerationStructuresKHR
、 vkCmdCopyAccelerationStructureKHR
和 vkCopyAccelerationStructureKHR
函数实现的。
在将缓存输入构建加速结构指令构建加速结构时,如何构建加速结构是设备自己内部实现。
正确用法
必须激活
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
要么指向VkAccelerationStructureMotionInfoNV
或VkOpaqueCaptureDescriptorDataCreateInfoEXT
。createFlags 是
VkAccelerationStructureCreateFlagBitsKHR
的位域,用于创建加速结构时指定附加参数。buffer 加速结构将会存储的目标缓存。
offset 对于目标缓存的起始地址的比特偏移,在目标缓存的此偏移位置之后存储加速结构。偏移值必须是
256
的倍数。size 加速结构需要的大小。
type
VkAccelerationStructureTypeKHR
枚举值,用于创建的加速结构类型。deviceAddress 如果使用
accelerationStructureCaptureReplay
特性,需要该加速结构请求的设备地址。
如果 deviceAddress
为 0
的话,表示没有指定请求地址。
如果 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_KHR
或 VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR
。
如果加速结构将作为构建的目标,加速结构需要的大小可以通过 vkGetAccelerationStructureBuildSizesKHR
获取。如果加速结构用于压缩拷贝的话, vkCmdWriteAccelerationStructuresPropertiesKHR
或 vkWriteAccelerationStructuresPropertiesKHR
可以用于获取需要的压缩大小。
如果加速结构用于构建 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
给的是有效设备地址,该函数将返回与之相同的设备地址。
如果加速结构在创建时 type
是 VK_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 只是要构建的加速结构的个数。该个数为
pInfos
和ppBuildRangeInfos
需要提供的个数。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::srcAccelerationStructure
和 VkAccelerationStructureBuildGeometryInfoKHR::dstAccelerationStructure
时必须在 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段使用 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR
或 VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR
访问类型进行同步较适当。
访问其他的 VkAccelerationStructureGeometryTrianglesDataKHR::vertexData
、 VkAccelerationStructureGeometryTrianglesDataKHR::indexData
、 VkAccelerationStructureGeometryTrianglesDataKHR::transformData
、 VkAccelerationStructureGeometryAabbsDataKHR::data
和 VkAccelerationStructureGeometryInstancesDataKHR::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_KHR
,primitiveCount
是轴对齐包围盒的个数。将会从VkAccelerationStructureGeometryAabbsDataKHR::data
在primitiveOffset
偏移之后获取primitiveCount
个VkAabbPositionsKHR
结构体数据。对于类型为
VK_GEOMETRY_TYPE_INSTANCES_KHR
,primitiveCount
是加速结构的个数。将会从VkAccelerationStructureGeometryInstancesDataKHR::data
在primitiveOffset
偏移之后获取primitiveCount
个VkAccelerationStructureInstanceKHR
结构体数据。
正确用法
对于类型为
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_KHR
或 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段和 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR
访问类型进行同步。
如果
queryType
是VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR
的话,则返回的查询值就是加速结构压缩之后需要的比特数量。如果
queryType
是VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR
的话,则返回的查询值就是加速结构序列化之后需要的比特数量。
正确用法
需要激活
VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructure
特性queryPool
创建时的queryType
必须与vkCmdWriteAccelerationStructuresPropertiesKHR::queryType
相匹配。pAccelerationStructures
中的加速结构在必须通过buffer
绑定到了设备内存上。pAccelerationStructures
中的加速结构在调用该指令之前必须已经构建完成。如果
queryType
是VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR
的话,pAccelerationStructures
中所有的加速结构必须根据VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR
构建的。queryType
必须是VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR
或VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR
或VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR
或VK_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->src
和 pInfo->dst
必须使用 VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR
或 VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR
访问类型,在 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR
或 VK_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_KHR
或VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR
。src
的源加速结构在执行该指令前必须构建完成 。如果
mode
是VK_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_KHR 将
src
中的加速结构直接拷贝至dst
中,其中dst
的创建参数必须和src
的创建参数一样。如果src
引用了其他加速结构,dst
也需要进行相应的匹配。VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR 将
src
中的加速结构压缩版本拷贝至dst
中,其中dst
的加速结构大小最起码需要与src
构建之后使用vkCmdWriteAccelerationStructuresPropertiesKHR
或vkWriteAccelerationStructuresPropertiesKHR
获取到的大小一致。如果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_KHR
或 VK_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_KHR
或 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段使用 VK_ACCESS_TRANSFER_WRITE_BIT
访问类型进行同步。
该指令与 vkCopyAccelerationStructureToMemoryKHR
函数的结果相似,只不过 vkCmdCopyAccelerationStructureToMemoryKHR
是写入 device
地址中,并且在 device
端执行而不是在 host
端。这两个指令函数的输出结果不一定每一个比特位都相同,但是在使用上 vkCmdCopyMemoryToAccelerationStructureKHR
和 vkCopyMemoryToAccelerationStructureKHR
是一样的。
序列化数据头结构如下:
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 是拷贝目标
host
或device
内存地址。mode 是拷贝时的额外参数。
正确用法
src
的加速结构必须在执行拷贝指令前创建完成。dst
的内存大小最起码需要与使用VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR
查询类型调用vkWriteAccelerationStructuresPropertiesKHR
或vkCmdWriteAccelerationStructuresPropertiesKHR
函数获取到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_KHR
或 VK_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_KHR
或 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
管线阶段使用 VK_ACCESS_TRANSFER_READ_BIT
访问类型进行同步。
该指令支持使用 vkCmdCopyAccelerationStructureToMemoryKHR
或 vkCopyAccelerationStructureToMemoryKHR
拷贝的目标内存地址。
该指令的的反序列化将会作为 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 拷贝的源
host
或device
内存地址。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
端的函数时不需要应用将加速结构的内存映射出来。
备注
vkBuildAccelerationStructuresKHR
和 vkCmdBuildAccelerationStructuresKHR
也许会使用不同的算法,然而并没有要求这两个函数的结果需要完全相同。这两个函数可能会分别建立各自完全不同的内存或遍历性能,但是应该尽可能地尽量做到相似。
除了这些细节之外,Host
和 Device
操作是可互换兼容的。比如可以使用 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 表示要构建的加速结构数量。并表示
pInfos
和ppBuildRangeInfos
需要提供的数量。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->src
的buffer
必须绑定到Host
端可访问的内存上。用于
pInfo->dst
的buffer
必须绑定到Host
端可访问的内存上。用于
pInfo->src
的buffer
必须绑定到没有分配多实体的内存上。用于
pInfo->dst
的buffer
必须绑定到没有分配多实体的内存上。
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
端上。
该函数支持使用 vkCmdCopyAccelerationStructureToMemoryKHR
或 vkCopyAccelerationStructureToMemoryKHR
的加速结构内存。
正确用法
需要激活
VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructureHostCommands
特性。如果
deferredOperation
不是VK_NULL_HANDLE
的话,其必须是一个有效的VkDeferredOperationKHR
句柄。任何与
deferredOperation
相关的前操作都需要完成结束。用于
pInfo->src.hostAddress
必须是一个有效的Host
端指针。用于
pInfo->dst
的buffer
必须绑定到Host
端可访问的内存上。用于
pInfo->src.hostAddress
必须16
比特对齐。用于
pInfo->dst
的buffer
必须绑定到没有分配多实体的内存上。
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
端。每次输出的结果并不一定每一个比特都相等,但都可以被 vkCmdCopyMemoryToAccelerationStructureKHR
或 vkCopyMemoryToAccelerationStructureKHR
使用。
正确用法
需要激活
VkPhysicalDeviceAccelerationStructureFeaturesKHR::accelerationStructureHostCommands
特性。如果
deferredOperation
不是VK_NULL_HANDLE
的话,其必须是一个有效的VkDeferredOperationKHR
句柄。任何与
deferredOperation
相关的前操作都需要完成结束。用于
pInfo->src
的buffer
必须绑定到Host
端可访问的内存上。用于
pInfo->dst.hostAddress
必须是有效的Host
指针。用于
pInfo->dst.hostAddress
必须16
比特对齐。用于
pInfo->src
的buffer
必须绑定到没有分配多实体的内存上。
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 用于指向之前构建的加速结构数组。
queryType 是
VkQueryType
值用于设置查询类型。dataSize 是
pData
中数据的比特大小。pData 指向用户分配的缓存用于写入结果。
stride 指向这是写入的每个结果之间的跨度。
该函数的工作和 vkCmdWriteAccelerationStructuresPropertiesKHR
函数一致,只不过执行在 Host
端上。