Wrap buffer values in AccelerationStructureBuildGeometryInfo in an Option (#2307)

* Wrap buffer values in `AccelerationStructureBuildGeometryInfo` in an `Option`

* Oops!

* Also wrap `mode` and `dst_acceleration_structure`

* Un-wrap mode
This commit is contained in:
Rua 2023-08-26 11:53:37 +02:00 committed by GitHub
parent 10148c5e94
commit c8712dcecc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 171 additions and 40 deletions

View File

@ -454,13 +454,18 @@ pub struct AccelerationStructureBuildGeometryInfo {
/// The mode that the build command should operate in. /// The mode that the build command should operate in.
/// ///
/// This is ignored when calling [`Device::acceleration_structure_build_sizes`].
///
/// The default value is [`BuildAccelerationStructureMode::Build`]. /// The default value is [`BuildAccelerationStructureMode::Build`].
pub mode: BuildAccelerationStructureMode, pub mode: BuildAccelerationStructureMode,
/// The acceleration structure to build or update. /// The acceleration structure to build or update.
/// ///
/// This can be `None` when calling [`Device::acceleration_structure_build_sizes`],
/// but must be `Some` otherwise.
///
/// There is no default value. /// There is no default value.
pub dst_acceleration_structure: Arc<AccelerationStructure>, pub dst_acceleration_structure: Option<Arc<AccelerationStructure>>,
/// The geometries that will be built into `dst_acceleration_structure`. /// The geometries that will be built into `dst_acceleration_structure`.
/// ///
@ -474,27 +479,25 @@ pub struct AccelerationStructureBuildGeometryInfo {
/// Scratch memory to be used for the build. /// Scratch memory to be used for the build.
/// ///
/// There is no default value. /// This can be `None` when calling [`Device::acceleration_structure_build_sizes`],
pub scratch_data: Subbuffer<[u8]>, /// but must be `Some` otherwise.
///
/// The default value is `None`.
pub scratch_data: Option<Subbuffer<[u8]>>,
pub _ne: crate::NonExhaustive, pub _ne: crate::NonExhaustive,
} }
impl AccelerationStructureBuildGeometryInfo { impl AccelerationStructureBuildGeometryInfo {
/// Returns a `AccelerationStructureBuildGeometryInfo` with the specified /// Returns a `AccelerationStructureBuildGeometryInfo` with the specified `geometries`.
/// `dst_acceleration_structure`, `geometries` and `scratch_data`.
#[inline] #[inline]
pub fn new( pub fn new(geometries: AccelerationStructureGeometries) -> Self {
dst_acceleration_structure: Arc<AccelerationStructure>,
geometries: AccelerationStructureGeometries,
scratch_data: Subbuffer<[u8]>,
) -> Self {
Self { Self {
flags: BuildAccelerationStructureFlags::empty(), flags: BuildAccelerationStructureFlags::empty(),
mode: BuildAccelerationStructureMode::Build, mode: BuildAccelerationStructureMode::Build,
dst_acceleration_structure, dst_acceleration_structure: None,
geometries, geometries,
scratch_data, scratch_data: None,
_ne: crate::NonExhaustive(()), _ne: crate::NonExhaustive(()),
} }
} }
@ -571,8 +574,10 @@ impl AccelerationStructureBuildGeometryInfo {
} }
} }
// VUID-VkAccelerationStructureBuildGeometryInfoKHR-commonparent if let Some(dst_acceleration_structure) = dst_acceleration_structure {
assert_eq!(device, dst_acceleration_structure.device().as_ref()); // VUID-VkAccelerationStructureBuildGeometryInfoKHR-commonparent
assert_eq!(device, dst_acceleration_structure.device().as_ref());
}
if let BuildAccelerationStructureMode::Update(src_acceleration_structure) = mode { if let BuildAccelerationStructureMode::Update(src_acceleration_structure) = mode {
assert_eq!(device, src_acceleration_structure.device().as_ref()); assert_eq!(device, src_acceleration_structure.device().as_ref());
@ -633,10 +638,12 @@ impl AccelerationStructureBuildGeometryInfo {
triangles: ash::vk::AccelerationStructureGeometryTrianglesDataKHR { triangles: ash::vk::AccelerationStructureGeometryTrianglesDataKHR {
vertex_format: vertex_format.into(), vertex_format: vertex_format.into(),
vertex_data: ash::vk::DeviceOrHostAddressConstKHR { vertex_data: ash::vk::DeviceOrHostAddressConstKHR {
device_address: vertex_data device_address: vertex_data.as_ref().map_or(
.device_address() 0,
.unwrap() |vertex_data| {
.into(), vertex_data.device_address().unwrap().into()
},
),
}, },
vertex_stride: vertex_stride as DeviceSize, vertex_stride: vertex_stride as DeviceSize,
max_vertex, max_vertex,
@ -691,7 +698,9 @@ impl AccelerationStructureBuildGeometryInfo {
geometry: ash::vk::AccelerationStructureGeometryDataKHR { geometry: ash::vk::AccelerationStructureGeometryDataKHR {
aabbs: ash::vk::AccelerationStructureGeometryAabbsDataKHR { aabbs: ash::vk::AccelerationStructureGeometryAabbsDataKHR {
data: ash::vk::DeviceOrHostAddressConstKHR { data: ash::vk::DeviceOrHostAddressConstKHR {
device_address: data.device_address().unwrap().get(), device_address: data.as_ref().map_or(0, |data| {
data.device_address().unwrap().into()
}),
}, },
stride: stride as DeviceSize, stride: stride as DeviceSize,
..Default::default() ..Default::default()
@ -715,13 +724,17 @@ impl AccelerationStructureBuildGeometryInfo {
AccelerationStructureGeometryInstancesDataType::Values(data) => ( AccelerationStructureGeometryInstancesDataType::Values(data) => (
ash::vk::FALSE, ash::vk::FALSE,
ash::vk::DeviceOrHostAddressConstKHR { ash::vk::DeviceOrHostAddressConstKHR {
device_address: data.device_address().unwrap().get(), device_address: data
.as_ref()
.map_or(0, |data| data.device_address().unwrap().into()),
}, },
), ),
AccelerationStructureGeometryInstancesDataType::Pointers(data) => ( AccelerationStructureGeometryInstancesDataType::Pointers(data) => (
ash::vk::TRUE, ash::vk::TRUE,
ash::vk::DeviceOrHostAddressConstKHR { ash::vk::DeviceOrHostAddressConstKHR {
device_address: data.device_address().unwrap().get(), device_address: data
.as_ref()
.map_or(0, |data| data.device_address().unwrap().into()),
}, },
), ),
}; };
@ -755,12 +768,16 @@ impl AccelerationStructureBuildGeometryInfo {
src_acceleration_structure.handle() src_acceleration_structure.handle()
} }
}, },
dst_acceleration_structure: dst_acceleration_structure.handle(), dst_acceleration_structure: dst_acceleration_structure
.as_ref()
.map_or_else(Default::default, VulkanObject::handle),
geometry_count: 0, geometry_count: 0,
p_geometries: ptr::null(), p_geometries: ptr::null(),
pp_geometries: ptr::null(), pp_geometries: ptr::null(),
scratch_data: ash::vk::DeviceOrHostAddressKHR { scratch_data: ash::vk::DeviceOrHostAddressKHR {
device_address: scratch_data.device_address().unwrap().get(), device_address: scratch_data.as_ref().map_or(0, |scratch_data| {
scratch_data.device_address().unwrap().into()
}),
}, },
..Default::default() ..Default::default()
}, },
@ -940,8 +957,11 @@ pub struct AccelerationStructureGeometryTrianglesData {
/// The vertex data itself, consisting of an array of `vertex_format` values. /// The vertex data itself, consisting of an array of `vertex_format` values.
/// ///
/// There is no default value. /// This can be `None` when calling [`Device::acceleration_structure_build_sizes`],
pub vertex_data: Subbuffer<[u8]>, /// but must be `Some` otherwise.
///
/// The default value is `None`.
pub vertex_data: Option<Subbuffer<[u8]>>,
/// The number of bytes between the start of successive elements in `vertex_data`. /// The number of bytes between the start of successive elements in `vertex_data`.
/// ///
@ -975,13 +995,13 @@ pub struct AccelerationStructureGeometryTrianglesData {
impl AccelerationStructureGeometryTrianglesData { impl AccelerationStructureGeometryTrianglesData {
/// Returns a `AccelerationStructureGeometryTrianglesData` with the specified /// Returns a `AccelerationStructureGeometryTrianglesData` with the specified
/// `vertex_format` and `vertex_data`. /// `vertex_format`.
#[inline] #[inline]
pub fn new(vertex_format: Format, vertex_data: Subbuffer<[u8]>) -> Self { pub fn new(vertex_format: Format) -> Self {
Self { Self {
flags: GeometryFlags::empty(), flags: GeometryFlags::empty(),
vertex_format, vertex_format,
vertex_data, vertex_data: None,
vertex_stride: 0, vertex_stride: 0,
max_vertex: 0, max_vertex: 0,
index_data: None, index_data: None,
@ -1080,8 +1100,11 @@ pub struct AccelerationStructureGeometryAabbsData {
/// The AABB data itself, consisting of an array of [`AabbPositions`] structs. /// The AABB data itself, consisting of an array of [`AabbPositions`] structs.
/// ///
/// There is no default value. /// This can be `None` when calling [`Device::acceleration_structure_build_sizes`],
pub data: Subbuffer<[u8]>, /// but must be `Some` otherwise.
///
/// The default value is `None`.
pub data: Option<Subbuffer<[u8]>>,
/// The number of bytes between the start of successive elements in `data`. /// The number of bytes between the start of successive elements in `data`.
/// ///
@ -1093,18 +1116,19 @@ pub struct AccelerationStructureGeometryAabbsData {
pub _ne: crate::NonExhaustive, pub _ne: crate::NonExhaustive,
} }
impl AccelerationStructureGeometryAabbsData { impl Default for AccelerationStructureGeometryAabbsData {
/// Returns a `AccelerationStructureGeometryAabbsData` with the specified `data`.
#[inline] #[inline]
pub fn new(data: Subbuffer<[u8]>) -> Self { fn default() -> Self {
Self { Self {
flags: GeometryFlags::empty(), flags: GeometryFlags::empty(),
data, data: None,
stride: 0, stride: 0,
_ne: crate::NonExhaustive(()), _ne: crate::NonExhaustive(()),
} }
} }
}
impl AccelerationStructureGeometryAabbsData {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> { pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self { let &Self {
flags, flags,
@ -1195,11 +1219,17 @@ impl AccelerationStructureGeometryInstancesData {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum AccelerationStructureGeometryInstancesDataType { pub enum AccelerationStructureGeometryInstancesDataType {
/// The data buffer contains an array of [`AccelerationStructureInstance`] structures directly. /// The data buffer contains an array of [`AccelerationStructureInstance`] structures directly.
Values(Subbuffer<[AccelerationStructureInstance]>), ///
/// The inner value can be `None` when calling [`Device::acceleration_structure_build_sizes`],
/// but must be `Some` otherwise.
Values(Option<Subbuffer<[AccelerationStructureInstance]>>),
/// The data buffer contains an array of pointers to [`AccelerationStructureInstance`] /// The data buffer contains an array of pointers to [`AccelerationStructureInstance`]
/// structures. /// structures.
Pointers(Subbuffer<[DeviceSize]>), ///
/// The inner value can be `None` when calling [`Device::acceleration_structure_build_sizes`],
/// but must be `Some` otherwise.
Pointers(Option<Subbuffer<[DeviceSize]>>),
} }
impl From<Subbuffer<[AccelerationStructureInstance]>> impl From<Subbuffer<[AccelerationStructureInstance]>>
@ -1207,14 +1237,14 @@ impl From<Subbuffer<[AccelerationStructureInstance]>>
{ {
#[inline] #[inline]
fn from(value: Subbuffer<[AccelerationStructureInstance]>) -> Self { fn from(value: Subbuffer<[AccelerationStructureInstance]>) -> Self {
Self::Values(value) Self::Values(Some(value))
} }
} }
impl From<Subbuffer<[DeviceSize]>> for AccelerationStructureGeometryInstancesDataType { impl From<Subbuffer<[DeviceSize]>> for AccelerationStructureGeometryInstancesDataType {
#[inline] #[inline]
fn from(value: Subbuffer<[DeviceSize]>) -> Self { fn from(value: Subbuffer<[DeviceSize]>) -> Self {
Self::Pointers(value) Self::Pointers(Some(value))
} }
} }

View File

@ -662,6 +662,8 @@ fn add_build_geometry_resources(
_ne, _ne,
} = triangles_data; } = triangles_data;
let vertex_data = vertex_data.as_ref().unwrap();
[ [
( (
ResourceInCommand::GeometryTrianglesVertexData { index }.into(), ResourceInCommand::GeometryTrianglesVertexData { index }.into(),
@ -710,6 +712,8 @@ fn add_build_geometry_resources(
_ne: _, _ne: _,
} = aabbs_data; } = aabbs_data;
let data = data.as_ref().unwrap();
( (
ResourceInCommand::GeometryAabbsData { index }.into(), ResourceInCommand::GeometryAabbsData { index }.into(),
Resource::Buffer { Resource::Buffer {
@ -729,8 +733,14 @@ fn add_build_geometry_resources(
} = instances_data; } = instances_data;
let data = match data { let data = match data {
AccelerationStructureGeometryInstancesDataType::Values(data) => data.as_bytes(), AccelerationStructureGeometryInstancesDataType::Values(data) => {
AccelerationStructureGeometryInstancesDataType::Pointers(data) => data.as_bytes(), let data = data.as_ref().unwrap();
data.as_bytes()
}
AccelerationStructureGeometryInstancesDataType::Pointers(data) => {
let data = data.as_ref().unwrap();
data.as_bytes()
}
}; };
let size = data.size(); let size = data.size();
@ -759,6 +769,7 @@ fn add_build_geometry_resources(
)); ));
} }
let dst_acceleration_structure = dst_acceleration_structure.as_ref().unwrap();
let dst_buffer = dst_acceleration_structure.buffer(); let dst_buffer = dst_acceleration_structure.buffer();
used_resources.push(( used_resources.push((
ResourceInCommand::Destination.into(), ResourceInCommand::Destination.into(),
@ -769,6 +780,8 @@ fn add_build_geometry_resources(
PipelineStageAccessFlags::AccelerationStructureBuild_AccelerationStructureWrite, PipelineStageAccessFlags::AccelerationStructureBuild_AccelerationStructureWrite,
}, },
)); ));
let scratch_data = scratch_data.as_ref().unwrap();
used_resources.push(( used_resources.push((
ResourceInCommand::ScratchData.into(), ResourceInCommand::ScratchData.into(),
Resource::Buffer { Resource::Buffer {
@ -839,6 +852,22 @@ where
_ne, _ne,
} = info; } = info;
let dst_acceleration_structure =
dst_acceleration_structure
.as_ref()
.ok_or(Box::new(ValidationError {
context: "info.dst_acceleration_structure".into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
let scratch_data = scratch_data.as_ref().ok_or(Box::new(ValidationError {
context: "info.scratch_data".into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
// VUID-vkCmdBuildAccelerationStructuresKHR-mode-04628 // VUID-vkCmdBuildAccelerationStructuresKHR-mode-04628
// Ensured as long as `BuildAccelerationStructureMode` is exhaustive. // Ensured as long as `BuildAccelerationStructureMode` is exhaustive.
@ -968,6 +997,13 @@ where
_ne, _ne,
} = triangles_data; } = triangles_data;
let vertex_data = vertex_data.as_ref().ok_or(Box::new(ValidationError {
context: format!("info.geometries[{}].vertex_data", geometry_index).into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
let &AccelerationStructureBuildRangeInfo { let &AccelerationStructureBuildRangeInfo {
primitive_count, primitive_count,
primitive_offset, primitive_offset,
@ -1217,6 +1253,13 @@ where
_ne, _ne,
} = aabbs_data; } = aabbs_data;
let data = data.as_ref().ok_or(Box::new(ValidationError {
context: format!("info.geometries[{}].data", geometry_index).into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
let &AccelerationStructureBuildRangeInfo { let &AccelerationStructureBuildRangeInfo {
primitive_count, primitive_count,
primitive_offset, primitive_offset,
@ -1329,6 +1372,13 @@ where
let data_buffer = match data { let data_buffer = match data {
AccelerationStructureGeometryInstancesDataType::Values(data) => { AccelerationStructureGeometryInstancesDataType::Values(data) => {
let data = data.as_ref().ok_or(Box::new(ValidationError {
context: "info.geometries.data".into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
if data.device_address().unwrap().get() % 16 != 0 { if data.device_address().unwrap().get() % 16 != 0 {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
context: "info.geometries.data".into(), context: "info.geometries.data".into(),
@ -1363,6 +1413,13 @@ where
data.buffer() data.buffer()
} }
AccelerationStructureGeometryInstancesDataType::Pointers(data) => { AccelerationStructureGeometryInstancesDataType::Pointers(data) => {
let data = data.as_ref().ok_or(Box::new(ValidationError {
context: "info.geometries.data".into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
if !data if !data
.buffer() .buffer()
.usage() .usage()
@ -1600,6 +1657,22 @@ where
_ne, _ne,
} = info; } = info;
let dst_acceleration_structure =
dst_acceleration_structure
.as_ref()
.ok_or(Box::new(ValidationError {
context: "info.dst_acceleration_structure".into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
let scratch_data = scratch_data.as_ref().ok_or(Box::new(ValidationError {
context: "info.scratch_data".into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
// VUID-vkCmdBuildAccelerationStructuresIndirectKHR-mode-04628 // VUID-vkCmdBuildAccelerationStructuresIndirectKHR-mode-04628
// Ensured as long as `BuildAccelerationStructureMode` is exhaustive. // Ensured as long as `BuildAccelerationStructureMode` is exhaustive.
@ -1716,6 +1789,13 @@ where
_ne, _ne,
} = triangles_data; } = triangles_data;
let vertex_data = vertex_data.as_ref().ok_or(Box::new(ValidationError {
context: format!("info.geometries[{}].vertex_data", geometry_index).into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
// VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03795 // VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03795
// unsafe // unsafe
@ -1855,6 +1935,13 @@ where
_ne, _ne,
} = aabbs_data; } = aabbs_data;
let data = data.as_ref().ok_or(Box::new(ValidationError {
context: format!("info.geometries[{}].data", geometry_index).into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
// VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03794 // VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03794
// unsafe // unsafe
@ -1902,6 +1989,13 @@ where
let data_buffer = match data { let data_buffer = match data {
AccelerationStructureGeometryInstancesDataType::Values(data) => { AccelerationStructureGeometryInstancesDataType::Values(data) => {
let data = data.as_ref().ok_or(Box::new(ValidationError {
context: "info.geometries.data".into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
if data.device_address().unwrap().get() % 16 != 0 { if data.device_address().unwrap().get() % 16 != 0 {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
context: "info.geometries.data".into(), context: "info.geometries.data".into(),
@ -1919,6 +2013,13 @@ where
data.buffer() data.buffer()
} }
AccelerationStructureGeometryInstancesDataType::Pointers(data) => { AccelerationStructureGeometryInstancesDataType::Pointers(data) => {
let data = data.as_ref().ok_or(Box::new(ValidationError {
context: "info.geometries.data".into(),
problem: "is `None`".into(),
// vuids?
..Default::default()
}))?;
if !data if !data
.buffer() .buffer()
.usage() .usage()