diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ff81548..ef3b86f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.7.1] - 2022-12-17 + +### Fixed + +- Soundness issue in `AccelerationStructure::instance_slice` helper function ### Added @@ -289,4 +293,5 @@ _See [#25](https://github.com/attackgoat/screen-13/pull/25) for migration detail [0.6.3]: https://crates.io/crates/screen-13/0.6.3 [0.6.4]: https://crates.io/crates/screen-13/0.6.4 [0.6.5]: https://crates.io/crates/screen-13/0.6.5 -[0.7.0]: https://crates.io/crates/screen-13/0.7.0 \ No newline at end of file +[0.7.0]: https://crates.io/crates/screen-13/0.7.0 +[0.7.1]: https://crates.io/crates/screen-13/0.7.1 \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 959e8ba0..51a5c95a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "screen-13" -version = "0.7.0" +version = "0.7.1" authors = ["John Wells "] edition = "2021" license = "MIT OR Apache-2.0" diff --git a/contrib/screen-13-egui/src/lib.rs b/contrib/screen-13-egui/src/lib.rs index 2946a14e..b40024aa 100644 --- a/contrib/screen-13-egui/src/lib.rs +++ b/contrib/screen-13-egui/src/lib.rs @@ -257,13 +257,13 @@ impl Egui { let num_indices = mesh.indices.len() as u32; - let clip_x = (clip_rect.min.x as f32 * pixels_per_point) as i32; - let clip_y = (clip_rect.min.y as f32 * pixels_per_point) as i32; + let clip_x = (clip_rect.min.x * pixels_per_point) as i32; + let clip_y = (clip_rect.min.y * pixels_per_point) as i32; let clip_width = - ((clip_rect.max.x - clip_rect.min.x) as f32 * pixels_per_point) as u32; + ((clip_rect.max.x - clip_rect.min.x) * pixels_per_point) as u32; let clip_height = - ((clip_rect.max.y - clip_rect.min.y) as f32 * pixels_per_point) as u32; + ((clip_rect.max.y - clip_rect.min.y) * pixels_per_point) as u32; render_graph .begin_pass("Egui pass") diff --git a/contrib/screen-13-fx/src/image_loader.rs b/contrib/screen-13-fx/src/image_loader.rs index 4a6a2909..ddac1575 100644 --- a/contrib/screen-13-fx/src/image_loader.rs +++ b/contrib/screen-13-fx/src/image_loader.rs @@ -153,7 +153,7 @@ impl ImageLoader { //trace!("{bitmap_width}x{bitmap_height} Stride={bitmap_stride}"); - let pixel_buf_stride = align_up_u32(stride as u32, 12); + let pixel_buf_stride = align_up_u32(stride, 12); let pixel_buf_len = (pixel_buf_stride * height) as vk::DeviceSize; //trace!("pixel_buf_len={pixel_buf_len} pixel_buf_stride={pixel_buf_stride}"); diff --git a/contrib/screen-13-fx/src/transition.rs b/contrib/screen-13-fx/src/transition.rs index 243ec076..8652dcda 100644 --- a/contrib/screen-13-fx/src/transition.rs +++ b/contrib/screen-13-fx/src/transition.rs @@ -449,7 +449,7 @@ impl TransitionPipeline { let a_image = a_image.into(); let b_image = b_image.into(); let dest_image = dest_image.into(); - let progress = progress.max(0.0).min(1.0); + let progress = progress.clamp(0.0, 1.0); let dest_info = render_graph.node_info(dest_image); diff --git a/examples/fuzzer.rs b/examples/fuzzer.rs index 5b4703af..047ac571 100644 --- a/examples/fuzzer.rs +++ b/examples/fuzzer.rs @@ -159,6 +159,13 @@ fn record_accel_struct_builds(frame: &mut FrameContext, pool: &mut HashPool) { ) .unwrap(); + let scratch_buf_padding = frame + .device + .accel_struct_properties + .as_ref() + .unwrap() + .min_accel_struct_scratch_offset_alignment as vk::DeviceSize; + // Lease and bind a bunch of bottom-level acceleration structures and add to instance buffer let mut blas_nodes = Vec::with_capacity(BLAS_COUNT as _); for idx in 0..BLAS_COUNT { @@ -167,7 +174,7 @@ fn record_accel_struct_builds(frame: &mut FrameContext, pool: &mut HashPool) { Buffer::copy_from_slice( &mut instance_buf, idx * instance_len, - AccelerationStructure::instance_slice(vk::AccelerationStructureInstanceKHR { + AccelerationStructure::instance_slice(&[vk::AccelerationStructureInstanceKHR { transform: vk::TransformMatrixKHR { matrix: [ 1.0, 0.0, 0.0, 0.0, // @@ -183,13 +190,13 @@ fn record_accel_struct_builds(frame: &mut FrameContext, pool: &mut HashPool) { acceleration_structure_reference: vk::AccelerationStructureReferenceKHR { device_handle: AccelerationStructure::device_address(&blas), }, - }), + }]), ); let blas_node = frame.render_graph.bind_node(blas); let scratch_buf = frame.render_graph.bind_node( pool.lease(BufferInfo::new( - blas_size.build_size, + blas_size.build_size + scratch_buf_padding, vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS | vk::BufferUsageFlags::STORAGE_BUFFER, )) .unwrap(), @@ -211,6 +218,7 @@ fn record_accel_struct_builds(frame: &mut FrameContext, pool: &mut HashPool) { }, }], }; + let instance_buf = frame.render_graph.bind_node(instance_buf); let tlas_size = AccelerationStructure::size_of(frame.device, &tlas_geometry_info); let tlas = pool .lease(AccelerationStructureInfo { @@ -221,7 +229,7 @@ fn record_accel_struct_builds(frame: &mut FrameContext, pool: &mut HashPool) { let tlas_node = frame.render_graph.bind_node(tlas); let tlas_scratch_buf = frame.render_graph.bind_node( pool.lease(BufferInfo::new( - tlas_size.build_size, + tlas_size.build_size + scratch_buf_padding, vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS | vk::BufferUsageFlags::STORAGE_BUFFER, )) .unwrap(), @@ -269,6 +277,7 @@ fn record_accel_struct_builds(frame: &mut FrameContext, pool: &mut HashPool) { pass.access_node_mut(blas_node, AccessType::AccelerationStructureBuildRead); } + pass.access_node_mut(instance_buf, AccessType::AccelerationStructureBuildRead); pass.access_node_mut( tlas_scratch_buf, AccessType::AccelerationStructureBufferWrite, diff --git a/examples/ray_trace.rs b/examples/ray_trace.rs index 431aeac7..ad5a08f3 100644 --- a/examples/ray_trace.rs +++ b/examples/ray_trace.rs @@ -597,7 +597,7 @@ fn main() -> anyhow::Result<()> { // Create an instance buffer, which is just one instance for the single BLAS // ------------------------------------------------------------------------------------------ // - let instance = AccelerationStructure::instance_slice(vk::AccelerationStructureInstanceKHR { + let instances = [vk::AccelerationStructureInstanceKHR { transform: vk::TransformMatrixKHR { matrix: [ 1.0, 0.0, 0.0, 0.0, // @@ -613,17 +613,18 @@ fn main() -> anyhow::Result<()> { acceleration_structure_reference: vk::AccelerationStructureReferenceKHR { device_handle: blas_device_address, }, - }); + }]; + let instance_data = AccelerationStructure::instance_slice(&instances); let instance_buf = Arc::new({ let mut buffer = Buffer::create( &event_loop.device, BufferInfo::new_mappable( - instance.len() as _, + instance_data.len() as _, vk::BufferUsageFlags::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS, ), )?; - Buffer::copy_from_slice(&mut buffer, 0, instance); + Buffer::copy_from_slice(&mut buffer, 0, instance_data); buffer }); @@ -658,6 +659,13 @@ fn main() -> anyhow::Result<()> { // ------------------------------------------------------------------------------------------ // { + let scratch_buf_padding = event_loop + .device + .accel_struct_properties + .as_ref() + .unwrap() + .min_accel_struct_scratch_offset_alignment + as vk::DeviceSize; let mut render_graph = RenderGraph::new(); let index_node = render_graph.bind_node(&index_buf); let vertex_node = render_graph.bind_node(&vertex_buf); @@ -667,7 +675,7 @@ fn main() -> anyhow::Result<()> { let scratch_buf = render_graph.bind_node(Buffer::create( &event_loop.device, BufferInfo::new( - blas_size.build_size, + blas_size.build_size + scratch_buf_padding, vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS | vk::BufferUsageFlags::STORAGE_BUFFER, ), @@ -675,10 +683,10 @@ fn main() -> anyhow::Result<()> { render_graph .begin_pass("Build BLAS") - .read_node(index_node) - .read_node(vertex_node) - .write_node(blas_node) - .write_node(scratch_buf) + .access_node(index_node, AccessType::AccelerationStructureBuildRead) + .access_node(vertex_node, AccessType::AccelerationStructureBuildRead) + .access_node(scratch_buf, AccessType::AccelerationStructureBufferWrite) + .access_node(blas_node, AccessType::AccelerationStructureBuildWrite) .record_acceleration(move |accel, _| { accel.build_structure( blas_node, @@ -698,7 +706,7 @@ fn main() -> anyhow::Result<()> { let scratch_buf = render_graph.bind_node(Buffer::create( &event_loop.device, BufferInfo::new( - tlas_size.build_size, + tlas_size.build_size + scratch_buf_padding, vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS | vk::BufferUsageFlags::STORAGE_BUFFER, ), @@ -708,10 +716,10 @@ fn main() -> anyhow::Result<()> { render_graph .begin_pass("Build TLAS") - .read_node(blas_node) - .read_node(instance_node) - .write_node(scratch_buf) - .write_node(tlas_node) + .access_node(blas_node, AccessType::AccelerationStructureBuildRead) + .access_node(instance_node, AccessType::AccelerationStructureBuildRead) + .access_node(scratch_buf, AccessType::AccelerationStructureBufferWrite) + .access_node(tlas_node, AccessType::AccelerationStructureBuildWrite) .record_acceleration(move |accel, _| { accel.build_structure( tlas_node, diff --git a/examples/rt_triangle.rs b/examples/rt_triangle.rs index fdd93b7b..e27b1d7c 100644 --- a/examples/rt_triangle.rs +++ b/examples/rt_triangle.rs @@ -262,7 +262,7 @@ fn main() -> anyhow::Result<()> { // Create an instance buffer, which is just one instance for the single BLAS // ------------------------------------------------------------------------------------------ // - let instance = AccelerationStructure::instance_slice(vk::AccelerationStructureInstanceKHR { + let instances = [vk::AccelerationStructureInstanceKHR { transform: vk::TransformMatrixKHR { matrix: [ 1.0, 0.0, 0.0, 0.0, // @@ -278,17 +278,18 @@ fn main() -> anyhow::Result<()> { acceleration_structure_reference: vk::AccelerationStructureReferenceKHR { device_handle: blas_device_address, }, - }); + }]; + let instance_data = AccelerationStructure::instance_slice(&instances); let instance_buf = Arc::new({ let mut buffer = Buffer::create( &event_loop.device, BufferInfo::new_mappable( - instance.len() as _, + instance_data.len() as _, vk::BufferUsageFlags::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS, ), )?; - Buffer::copy_from_slice(&mut buffer, 0, instance); + Buffer::copy_from_slice(&mut buffer, 0, instance_data); buffer }); @@ -323,6 +324,13 @@ fn main() -> anyhow::Result<()> { // ------------------------------------------------------------------------------------------ // { + let scratch_buf_padding = event_loop + .device + .accel_struct_properties + .as_ref() + .unwrap() + .min_accel_struct_scratch_offset_alignment + as vk::DeviceSize; let mut render_graph = RenderGraph::new(); let index_node = render_graph.bind_node(&index_buf); let vertex_node = render_graph.bind_node(&vertex_buf); @@ -332,7 +340,7 @@ fn main() -> anyhow::Result<()> { let scratch_buf = render_graph.bind_node(Buffer::create( &event_loop.device, BufferInfo::new( - blas_size.build_size, + blas_size.build_size + scratch_buf_padding, vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS | vk::BufferUsageFlags::STORAGE_BUFFER, ), @@ -340,10 +348,10 @@ fn main() -> anyhow::Result<()> { render_graph .begin_pass("Build BLAS") - .read_node(index_node) - .read_node(vertex_node) - .write_node(blas_node) - .write_node(scratch_buf) + .access_node(index_node, AccessType::AccelerationStructureBuildRead) + .access_node(vertex_node, AccessType::AccelerationStructureBuildRead) + .access_node(scratch_buf, AccessType::AccelerationStructureBufferWrite) + .access_node(blas_node, AccessType::AccelerationStructureBuildWrite) .record_acceleration(move |accel, _| { accel.build_structure( blas_node, @@ -355,28 +363,28 @@ fn main() -> anyhow::Result<()> { primitive_offset: 0, transform_offset: 0, }], - ) + ); }); } { + let instance_node = render_graph.bind_node(instance_buf); let scratch_buf = render_graph.bind_node(Buffer::create( &event_loop.device, BufferInfo::new( - tlas_size.build_size, + tlas_size.build_size + scratch_buf_padding, vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS | vk::BufferUsageFlags::STORAGE_BUFFER, ), )?); - let instance_node = render_graph.bind_node(&instance_buf); let tlas_node = render_graph.bind_node(&tlas); render_graph .begin_pass("Build TLAS") - .read_node(blas_node) - .read_node(instance_node) - .write_node(scratch_buf) - .write_node(tlas_node) + .access_node(blas_node, AccessType::AccelerationStructureBuildRead) + .access_node(instance_node, AccessType::AccelerationStructureBuildRead) + .access_node(scratch_buf, AccessType::AccelerationStructureBufferWrite) + .access_node(tlas_node, AccessType::AccelerationStructureBuildWrite) .record_acceleration(move |accel, _| { accel.build_structure( tlas_node, diff --git a/examples/shader-toy/build.rs b/examples/shader-toy/build.rs index 675e9518..676774c6 100644 --- a/examples/shader-toy/build.rs +++ b/examples/shader-toy/build.rs @@ -74,7 +74,7 @@ fn compile_glsl(path: impl AsRef, kind: ShaderKind) -> anyhow::Result<(Pat "{}.spirv", source_path.extension().unwrap().to_string_lossy() )); - write(&spirv_path, &spirv).context("Unable to write SPIR-V binary")?; + write(&spirv_path, spirv).context("Unable to write SPIR-V binary")?; Ok((source_path, spirv_path)) } diff --git a/src/driver/accel_struct.rs b/src/driver/accel_struct.rs index c431b9a9..da016214 100644 --- a/src/driver/accel_struct.rs +++ b/src/driver/accel_struct.rs @@ -214,11 +214,11 @@ impl AccelerationStructure { } /// Helper function which is used to prepare instance buffers. - pub fn instance_slice<'a>(instance: vk::AccelerationStructureInstanceKHR) -> &'a [u8] { + pub fn instance_slice(instances: &[vk::AccelerationStructureInstanceKHR]) -> &[u8] { unsafe { std::slice::from_raw_parts( - &instance as *const _ as *const _, - size_of::(), + instances.as_ptr() as *const _, + instances.len() * size_of::(), ) } } diff --git a/src/driver/compute.rs b/src/driver/compute.rs index 64e319a7..d5671189 100644 --- a/src/driver/compute.rs +++ b/src/driver/compute.rs @@ -88,8 +88,8 @@ impl ComputePipeline { let descriptor_info = PipelineDescriptorInfo::create(&device, &descriptor_bindings)?; let descriptor_set_layouts = descriptor_info .layouts - .iter() - .map(|(_, descriptor_set_layout)| **descriptor_set_layout) + .values() + .map(|descriptor_set_layout| **descriptor_set_layout) .collect::>(); unsafe { diff --git a/src/driver/device.rs b/src/driver/device.rs index 4af7d51d..0ee5740f 100644 --- a/src/driver/device.rs +++ b/src/driver/device.rs @@ -1,8 +1,9 @@ use { super::{ DriverConfig, DriverError, Instance, PhysicalDevice, - PhysicalDeviceDepthStencilResolveProperties, PhysicalDeviceDescriptorIndexingFeatures, - PhysicalDeviceRayTracePipelineProperties, Queue, SamplerDesc, Surface, + PhysicalDeviceAccelerationStructureProperties, PhysicalDeviceDepthStencilResolveProperties, + PhysicalDeviceDescriptorIndexingFeatures, PhysicalDeviceRayTracePipelineProperties, Queue, + SamplerDesc, Surface, }, ash::{extensions::khr, vk}, gpu_allocator::{ @@ -28,6 +29,11 @@ use { /// Opaque handle to a device object. pub struct Device { pub(crate) accel_struct_ext: Option, + + /// Describes the properties of the device which relate to acceleration structures, if + /// available. + pub accel_struct_properties: Option, + pub(super) allocator: Option>, /// Describes the properties of the device which relate to depth/stencil resolve operations. @@ -306,6 +312,8 @@ impl Device { } } + let mut accel_struct_properties = + vk::PhysicalDeviceAccelerationStructurePropertiesKHR::default(); let mut ray_tracing_pipeline_properties = vk::PhysicalDeviceRayTracingPipelinePropertiesKHR::default(); @@ -317,8 +325,9 @@ impl Device { physical_properties.push_next(&mut depth_stencil_resolve_properties); if features.ray_tracing { - physical_properties = - physical_properties.push_next(&mut ray_tracing_pipeline_properties); + physical_properties = physical_properties + .push_next(&mut accel_struct_properties) + .push_next(&mut ray_tracing_pipeline_properties); } let mut physical_properties = physical_properties.build(); @@ -326,10 +335,14 @@ impl Device { let depth_stencil_resolve_properties = depth_stencil_resolve_properties.into(); - let ray_tracing_pipeline_properties = if features.ray_tracing { - Some(ray_tracing_pipeline_properties.into()) + let (accel_struct_properties, ray_tracing_pipeline_properties) = if features.ray_tracing + { + ( + Some(accel_struct_properties.into()), + Some(ray_tracing_pipeline_properties.into()), + ) } else { - None + (None, None) }; let queue_infos = [queue_info]; @@ -394,6 +407,7 @@ impl Device { Ok(Self { accel_struct_ext, + accel_struct_properties, allocator: Some(Mutex::new(allocator)), depth_stencil_resolve_properties, descriptor_indexing_features, diff --git a/src/driver/graphic.rs b/src/driver/graphic.rs index 25ce8372..fda510d7 100644 --- a/src/driver/graphic.rs +++ b/src/driver/graphic.rs @@ -458,8 +458,8 @@ impl GraphicPipeline { let descriptor_info = PipelineDescriptorInfo::create(&device, &descriptor_bindings)?; let descriptor_sets_layouts = descriptor_info .layouts - .iter() - .map(|(_, descriptor_set_layout)| **descriptor_set_layout) + .values() + .map(|descriptor_set_layout| **descriptor_set_layout) .collect::>(); let push_constants = shaders diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 99d8f2af..fc892339 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -870,6 +870,55 @@ impl Display for DriverError { impl Error for DriverError {} +/// Properties of the physical device for acceleration structures. +#[derive(Debug)] +pub struct PhysicalDeviceAccelerationStructureProperties { + /// The maximum number of geometries in a bottom level acceleration structure. + pub max_geometry_count: u64, + + /// The maximum number of instances in a top level acceleration structure. + pub max_instance_count: u64, + + /// The maximum number of triangles or AABBs in all geometries in a bottom level acceleration + /// structure. + pub max_primitive_count: u64, + + /// The maximum number of acceleration structure bindings that can be accessible to a single + /// shader stage in a pipeline layout. + /// + /// Descriptor bindings with a descriptor type of + /// `VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR` count against this limit. + pub max_per_stage_descriptor_accel_structs: u32, + + /// The maximum number of acceleration structure descriptors that can be included in descriptor + /// bindings in a pipeline layout across all pipeline shader stages and descriptor set numbers. + /// + /// Descriptor bindings with a descriptor type of + /// `VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR` count against this limit. + pub max_descriptor_set_accel_structs: u32, + + /// The minimum required alignment, in bytes, for scratch data passed in to an acceleration + /// structure build command. + pub min_accel_struct_scratch_offset_alignment: u32, +} + +impl From + for PhysicalDeviceAccelerationStructureProperties +{ + fn from(props: vk::PhysicalDeviceAccelerationStructurePropertiesKHR) -> Self { + Self { + max_geometry_count: props.max_geometry_count, + max_instance_count: props.max_instance_count, + max_primitive_count: props.max_primitive_count, + max_per_stage_descriptor_accel_structs: props + .max_per_stage_descriptor_acceleration_structures, + max_descriptor_set_accel_structs: props.max_descriptor_set_acceleration_structures, + min_accel_struct_scratch_offset_alignment: props + .min_acceleration_structure_scratch_offset_alignment, + } + } +} + /// Structure describing depth/stencil resolve properties that can be supported by an /// implementation. #[derive(Debug)] diff --git a/src/driver/ray_trace.rs b/src/driver/ray_trace.rs index 430d3128..e8890365 100644 --- a/src/driver/ray_trace.rs +++ b/src/driver/ray_trace.rs @@ -135,8 +135,8 @@ impl RayTracePipeline { let descriptor_info = PipelineDescriptorInfo::create(device, &descriptor_bindings)?; let descriptor_set_layout_handles = descriptor_info .layouts - .iter() - .map(|(_, descriptor_set_layout)| **descriptor_set_layout) + .values() + .map(|descriptor_set_layout| **descriptor_set_layout) .collect::>(); unsafe { diff --git a/src/graph/mod.rs b/src/graph/mod.rs index 1898f77a..dad8e62a 100644 --- a/src/graph/mod.rs +++ b/src/graph/mod.rs @@ -621,8 +621,8 @@ impl RenderGraph { }, dst_offset: vk::Offset3D { x: 0, y: 0, z: 0 }, extent: vk::Extent3D { - depth: src_info.depth.min(dst_info.depth).max(1), - height: src_info.height.min(dst_info.height).max(1), + depth: src_info.depth.clamp(1, dst_info.depth), + height: src_info.height.clamp(1, dst_info.height), width: src_info.width.min(dst_info.width), }, }, diff --git a/src/graph/pass_ref.rs b/src/graph/pass_ref.rs index 949ef441..38097b51 100644 --- a/src/graph/pass_ref.rs +++ b/src/graph/pass_ref.rs @@ -40,6 +40,10 @@ pub type BindingOffset = u32; /// Alias for the descriptor set index of a shader descriptor. pub type DescriptorSetIndex = u32; +fn align_up_device_size(val: vk::DeviceSize, atom: vk::DeviceSize) -> vk::DeviceSize { + (val + atom - 1) & !(atom - 1) +} + /// Recording interface for acceleration structure commands. /// /// This structure provides a strongly-typed set of methods which allow acceleration structures to @@ -80,7 +84,8 @@ impl<'a> Acceleration<'a> { /// /// - Flags must include [`vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS`] /// - Size must be equal to or greater than the `build_size` value returned by - /// [`AccelerationStructure::size_of`]. + /// [`AccelerationStructure::size_of`] plus + /// `min_accel_struct_scratch_offset_alignment` of [`Device::accel_struct_properties`]. /// /// # Examples /// @@ -187,13 +192,21 @@ impl<'a> Acceleration<'a> { .geometries(&tls.geometries) .dst_acceleration_structure(*self.bindings[accel_struct_node]) .scratch_data(vk::DeviceOrHostAddressKHR { - device_address: Buffer::device_address(&self.bindings[scratch_buf_node]), + device_address: align_up_device_size( + Buffer::device_address(&self.bindings[scratch_buf_node]), + self.device + .accel_struct_properties + .as_ref() + .expect("ray tracing feature must be enabled") + .min_accel_struct_scratch_offset_alignment + as _, + ), }); self.device .accel_struct_ext .as_ref() - .unwrap() + .expect("ray tracing feature must be enabled") .cmd_build_acceleration_structures( self.cmd_buf, from_ref(&info), @@ -209,7 +222,8 @@ impl<'a> Acceleration<'a> { /// /// - Flags must include [`vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS`] /// - Size must be equal to or greater than the `update_size` value returned by - /// [`AccelerationStructure::size_of`]. + /// [`AccelerationStructure::size_of`] plus + /// `min_accel_struct_scratch_offset_alignment` of [`Device::accel_struct_properties`]. pub fn update_structure( &self, src_accel_node: impl Into, @@ -253,13 +267,21 @@ impl<'a> Acceleration<'a> { .dst_acceleration_structure(*self.bindings[dst_accel_node]) .src_acceleration_structure(*self.bindings[src_accel_node]) .scratch_data(vk::DeviceOrHostAddressKHR { - device_address: Buffer::device_address(&self.bindings[scratch_buf_node]), + device_address: align_up_device_size( + Buffer::device_address(&self.bindings[scratch_buf_node]), + self.device + .accel_struct_properties + .as_ref() + .expect("ray tracing feature must be enabled") + .min_accel_struct_scratch_offset_alignment + as _, + ), }); self.device .accel_struct_ext .as_ref() - .unwrap() + .expect("ray tracing feature must be enabled") .cmd_build_acceleration_structures( self.cmd_buf, from_ref(&info), diff --git a/src/lib.rs b/src/lib.rs index 835783fe..dfc7e645 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -340,8 +340,9 @@ pub mod prelude { }, shader::{Shader, ShaderBuilder, ShaderCode, SpecializationInfo}, AccessType, Device, Driver, DriverConfig, DriverConfigBuilder, DriverError, - FeatureFlags, PhysicalDevice, PhysicalDeviceDescriptorIndexingFeatures, - PhysicalDeviceRayTracePipelineProperties, ResolveMode, + FeatureFlags, PhysicalDevice, PhysicalDeviceAccelerationStructureProperties, + PhysicalDeviceDescriptorIndexingFeatures, PhysicalDeviceRayTracePipelineProperties, + ResolveMode, }, event_loop::{EventLoop, EventLoopBuilder, FullscreenMode}, frame::{center_cursor, set_cursor_position, FrameContext},