use super::device::DeviceInner;
use super::{Buffer, Device, Error, Result};
use crate::raw::bindings::*;
use crate::safe::auto::AccelerationStructureKHR;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccelerationStructureType {
BottomLevel,
TopLevel,
Generic,
}
impl AccelerationStructureType {
#[inline]
pub(crate) fn to_raw(self) -> VkAccelerationStructureTypeKHR {
match self {
Self::BottomLevel => {
VkAccelerationStructureTypeKHR::ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR
}
Self::TopLevel => {
VkAccelerationStructureTypeKHR::ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR
}
Self::Generic => {
VkAccelerationStructureTypeKHR::ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccelerationStructureBuildType {
Host,
Device,
HostOrDevice,
}
impl AccelerationStructureBuildType {
#[inline]
pub(crate) fn to_raw(self) -> VkAccelerationStructureBuildTypeKHR {
match self {
Self::Host => VkAccelerationStructureBuildTypeKHR::ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,
Self::Device => VkAccelerationStructureBuildTypeKHR::ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
Self::HostOrDevice => VkAccelerationStructureBuildTypeKHR::ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccelerationStructureBuildMode {
Build,
Update,
}
impl AccelerationStructureBuildMode {
#[inline]
pub(crate) fn to_raw(self) -> VkBuildAccelerationStructureModeKHR {
match self {
Self::Build => {
VkBuildAccelerationStructureModeKHR::BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR
}
Self::Update => {
VkBuildAccelerationStructureModeKHR::BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR
}
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct AccelerationStructureBuildFlags(pub u32);
impl AccelerationStructureBuildFlags {
pub const ALLOW_UPDATE: Self = Self(0x1);
pub const ALLOW_COMPACTION: Self = Self(0x2);
pub const PREFER_FAST_TRACE: Self = Self(0x4);
pub const PREFER_FAST_BUILD: Self = Self(0x8);
pub const LOW_MEMORY: Self = Self(0x10);
}
impl std::ops::BitOr for AccelerationStructureBuildFlags {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
#[derive(Debug, Clone, Copy)]
pub enum AccelerationStructureGeometry {
Triangles {
vertex_format: VkFormat,
vertex_data_address: u64,
vertex_stride: u64,
max_vertex: u32,
index_type: VkIndexType,
index_data_address: u64,
transform_data_address: u64,
},
Aabbs {
data_address: u64,
stride: u64,
},
Instances {
data_address: u64,
array_of_pointers: bool,
},
}
impl AccelerationStructureGeometry {
pub(crate) fn to_raw(self) -> VkAccelerationStructureGeometryKHR {
match self {
Self::Triangles {
vertex_format,
vertex_data_address,
vertex_stride,
max_vertex,
index_type,
index_data_address,
transform_data_address,
} => VkAccelerationStructureGeometryKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,
pNext: std::ptr::null(),
geometryType: VkGeometryTypeKHR::GEOMETRY_TYPE_TRIANGLES_KHR,
geometry: VkAccelerationStructureGeometryDataKHR {
triangles: VkAccelerationStructureGeometryTrianglesDataKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR,
pNext: std::ptr::null(),
vertexFormat: vertex_format,
vertexData: VkDeviceOrHostAddressConstKHR {
deviceAddress: vertex_data_address,
},
vertexStride: vertex_stride,
maxVertex: max_vertex,
indexType: index_type,
indexData: VkDeviceOrHostAddressConstKHR {
deviceAddress: index_data_address,
},
transformData: VkDeviceOrHostAddressConstKHR {
deviceAddress: transform_data_address,
},
},
},
flags: 0,
},
Self::Aabbs {
data_address,
stride,
} => VkAccelerationStructureGeometryKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,
pNext: std::ptr::null(),
geometryType: VkGeometryTypeKHR::GEOMETRY_TYPE_AABBS_KHR,
geometry: VkAccelerationStructureGeometryDataKHR {
aabbs: VkAccelerationStructureGeometryAabbsDataKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR,
pNext: std::ptr::null(),
data: VkDeviceOrHostAddressConstKHR {
deviceAddress: data_address,
},
stride,
},
},
flags: 0,
},
Self::Instances {
data_address,
array_of_pointers,
} => VkAccelerationStructureGeometryKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,
pNext: std::ptr::null(),
geometryType: VkGeometryTypeKHR::GEOMETRY_TYPE_INSTANCES_KHR,
geometry: VkAccelerationStructureGeometryDataKHR {
instances: VkAccelerationStructureGeometryInstancesDataKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR,
pNext: std::ptr::null(),
arrayOfPointers: array_of_pointers as VkBool32,
data: VkDeviceOrHostAddressConstKHR {
deviceAddress: data_address,
},
},
},
flags: 0,
},
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct BuildRange {
pub primitive_count: u32,
pub primitive_offset: u32,
pub first_vertex: u32,
pub transform_offset: u32,
}
impl BuildRange {
pub(crate) fn to_raw(self) -> VkAccelerationStructureBuildRangeInfoKHR {
VkAccelerationStructureBuildRangeInfoKHR {
primitiveCount: self.primitive_count,
primitiveOffset: self.primitive_offset,
firstVertex: self.first_vertex,
transformOffset: self.transform_offset,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct BuildSizes {
pub acceleration_structure_size: u64,
pub update_scratch_size: u64,
pub build_scratch_size: u64,
}
pub struct AccelerationStructure {
raw: AccelerationStructureKHR,
backing: Arc<Buffer>,
type_: AccelerationStructureType,
device: Arc<DeviceInner>,
}
pub struct AccelerationStructureCreateInfo<'a> {
pub buffer: Arc<Buffer>,
pub offset: u64,
pub size: u64,
pub type_: AccelerationStructureType,
pub _marker: std::marker::PhantomData<&'a ()>,
}
impl AccelerationStructure {
pub fn new(device: &Device, info: AccelerationStructureCreateInfo<'_>) -> Result<Self> {
let raw_info = VkAccelerationStructureCreateInfoKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR,
pNext: std::ptr::null(),
createFlags: 0,
buffer: info.buffer.raw(),
offset: info.offset,
size: info.size,
r#type: info.type_.to_raw(),
deviceAddress: 0,
};
let raw = AccelerationStructureKHR::create(device, &raw_info)?;
Ok(Self {
raw,
backing: info.buffer,
type_: info.type_,
device: Arc::clone(&device.inner),
})
}
pub fn raw(&self) -> VkAccelerationStructureKHR {
self.raw.raw()
}
pub fn type_(&self) -> AccelerationStructureType {
self.type_
}
pub fn backing_buffer(&self) -> &Arc<Buffer> {
&self.backing
}
pub fn device_address(&self) -> Result<u64> {
let f = self
.device
.dispatch
.vkGetAccelerationStructureDeviceAddressKHR
.ok_or(Error::MissingFunction(
"vkGetAccelerationStructureDeviceAddressKHR",
))?;
let info = VkAccelerationStructureDeviceAddressInfoKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR,
pNext: std::ptr::null(),
accelerationStructure: self.raw.raw(),
};
Ok(unsafe { f(self.device.handle, &info) })
}
}
impl Device {
pub fn acceleration_structure_build_sizes(
&self,
build_type: AccelerationStructureBuildType,
type_: AccelerationStructureType,
geometries: &[AccelerationStructureGeometry],
max_primitive_counts: &[u32],
flags: AccelerationStructureBuildFlags,
) -> Result<BuildSizes> {
if geometries.len() != max_primitive_counts.len() {
return Err(Error::InvalidArgument(
"geometries and max_primitive_counts must have equal length",
));
}
let f = self
.inner
.dispatch
.vkGetAccelerationStructureBuildSizesKHR
.ok_or(Error::MissingFunction(
"vkGetAccelerationStructureBuildSizesKHR",
))?;
let raw_geoms: Vec<VkAccelerationStructureGeometryKHR> =
geometries.iter().map(|g| g.to_raw()).collect();
let info = VkAccelerationStructureBuildGeometryInfoKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,
pNext: std::ptr::null(),
r#type: type_.to_raw(),
flags: flags.0,
mode: VkBuildAccelerationStructureModeKHR::BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,
srcAccelerationStructure: 0,
dstAccelerationStructure: 0,
geometryCount: raw_geoms.len() as u32,
pGeometries: if raw_geoms.is_empty() {
std::ptr::null()
} else {
raw_geoms.as_ptr()
},
ppGeometries: std::ptr::null(),
scratchData: VkDeviceOrHostAddressKHR { deviceAddress: 0 },
};
let mut sizes = VkAccelerationStructureBuildSizesInfoKHR {
sType: VkStructureType::STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR,
pNext: std::ptr::null_mut(),
accelerationStructureSize: 0,
updateScratchSize: 0,
buildScratchSize: 0,
};
unsafe {
f(
self.inner.handle,
build_type.to_raw(),
&info,
max_primitive_counts.as_ptr(),
&mut sizes,
)
};
Ok(BuildSizes {
acceleration_structure_size: sizes.accelerationStructureSize,
update_scratch_size: sizes.updateScratchSize,
build_scratch_size: sizes.buildScratchSize,
})
}
}