From 331c96cf28d185237405db8e8384dc41c9588561 Mon Sep 17 00:00:00 2001 From: ComfyFluffy <24245520+ComfyFluffy@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:22:50 +0800 Subject: [PATCH 1/3] refactor copy SBT handles --- vulkano/src/pipeline/ray_tracing.rs | 79 ++++++++++++++++++----------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/vulkano/src/pipeline/ray_tracing.rs b/vulkano/src/pipeline/ray_tracing.rs index abee90419c..c4d27a7471 100644 --- a/vulkano/src/pipeline/ray_tracing.rs +++ b/vulkano/src/pipeline/ray_tracing.rs @@ -393,6 +393,19 @@ impl RayTracingPipelineCreateInfo { ..Default::default() })); } + + let has_raygen = stages.iter().any(|stage| { + stage.entry_point.info().execution_model == ExecutionModel::RayGenerationKHR + }); + if !has_raygen { + return Err(Box::new(ValidationError { + context: "stages".into(), + problem: "does not contain a `RayGeneration` shader".into(), + vuids: &["VUID-VkRayTracingPipelineCreateInfoKHR-stage-03425"], + ..Default::default() + })); + } + for stage in stages { stage.validate(device).map_err(|err| { err.add_context("stages") @@ -819,11 +832,24 @@ impl ShaderBindingTable { allocator: Arc, ray_tracing_pipeline: &RayTracingPipeline, ) -> Result> { - let mut miss_shader_count: u64 = 0; - let mut hit_shader_count: u64 = 0; - let mut callable_shader_count: u64 = 0; + // VUID-vkCmdTraceRaysKHR-size-04023 + // There should be exactly one raygen shader group. + let mut raygen_shader_handle = None; + let mut miss_shader_handles = Vec::new(); + let mut hit_shader_handles = Vec::new(); + let mut callable_shader_handles = Vec::new(); + + let handle_data = ray_tracing_pipeline + .device() + .ray_tracing_shader_group_handles( + ray_tracing_pipeline, + 0, + ray_tracing_pipeline.groups().len() as u32, + )?; + let mut handle_iter = handle_data.iter(); for group in ray_tracing_pipeline.groups() { + let handle = handle_iter.next().unwrap(); match group { RayTracingShaderGroupCreateInfo::General { general_shader } => { match ray_tracing_pipeline.stages()[*general_shader as usize] @@ -831,9 +857,15 @@ impl ShaderBindingTable { .info() .execution_model { - ExecutionModel::RayGenerationKHR => {} - ExecutionModel::MissKHR => miss_shader_count += 1, - ExecutionModel::CallableKHR => callable_shader_count += 1, + ExecutionModel::RayGenerationKHR => { + raygen_shader_handle = Some(handle); + } + ExecutionModel::MissKHR => { + miss_shader_handles.push(handle); + } + ExecutionModel::CallableKHR => { + callable_shader_handles.push(handle); + } _ => { panic!("Unexpected shader type in general shader group"); } @@ -841,18 +873,12 @@ impl ShaderBindingTable { } RayTracingShaderGroupCreateInfo::ProceduralHit { .. } | RayTracingShaderGroupCreateInfo::TrianglesHit { .. } => { - hit_shader_count += 1; + hit_shader_handles.push(handle); } } } - let handle_data = ray_tracing_pipeline - .device() - .ray_tracing_shader_group_handles( - ray_tracing_pipeline, - 0, - ray_tracing_pipeline.groups().len() as u32, - )?; + let raygen_shader_handle = raygen_shader_handle.expect("no raygen shader group found"); let properties = ray_tracing_pipeline.device().physical_device().properties(); let handle_size_aligned = align_up( @@ -873,7 +899,7 @@ impl ShaderBindingTable { let mut miss = StridedDeviceAddressRegion { stride: handle_size_aligned, size: align_up( - handle_size_aligned * miss_shader_count, + handle_size_aligned * miss_shader_handles.len() as u64, shader_group_base_alignment, ), device_address: 0, @@ -881,7 +907,7 @@ impl ShaderBindingTable { let mut hit = StridedDeviceAddressRegion { stride: handle_size_aligned, size: align_up( - handle_size_aligned * hit_shader_count, + handle_size_aligned * hit_shader_handles.len() as u64, shader_group_base_alignment, ), device_address: 0, @@ -889,7 +915,7 @@ impl ShaderBindingTable { let mut callable = StridedDeviceAddressRegion { stride: handle_size_aligned, size: align_up( - handle_size_aligned * callable_shader_count, + handle_size_aligned * callable_shader_handles.len() as u64, shader_group_base_alignment, ), device_address: 0, @@ -920,26 +946,21 @@ impl ShaderBindingTable { { let mut sbt_buffer_write = sbt_buffer.write().unwrap(); - let mut handle_iter = handle_data.iter(); - let handle_size = handle_data.handle_size() as usize; - sbt_buffer_write[..handle_size].copy_from_slice(handle_iter.next().unwrap()); + sbt_buffer_write[..handle_size].copy_from_slice(raygen_shader_handle); let mut offset = raygen.size as usize; - for _ in 0..miss_shader_count { - sbt_buffer_write[offset..offset + handle_size] - .copy_from_slice(handle_iter.next().unwrap()); + for handle in miss_shader_handles { + sbt_buffer_write[offset..offset + handle_size].copy_from_slice(handle); offset += miss.stride as usize; } offset = (raygen.size + miss.size) as usize; - for _ in 0..hit_shader_count { - sbt_buffer_write[offset..offset + handle_size] - .copy_from_slice(handle_iter.next().unwrap()); + for handle in hit_shader_handles { + sbt_buffer_write[offset..offset + handle_size].copy_from_slice(handle); offset += hit.stride as usize; } offset = (raygen.size + miss.size + hit.size) as usize; - for _ in 0..callable_shader_count { - sbt_buffer_write[offset..offset + handle_size] - .copy_from_slice(handle_iter.next().unwrap()); + for handle in callable_shader_handles { + sbt_buffer_write[offset..offset + handle_size].copy_from_slice(handle); offset += callable.stride as usize; } } From 6c2e5caf31bc0b8a95892a081a53cdff61010914 Mon Sep 17 00:00:00 2001 From: ComfyFluffy <24245520+ComfyFluffy@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:27:40 +0800 Subject: [PATCH 2/3] switch to perspective_rh & refactor build_top_level_acceleration_structure --- examples/ray-tracing-auto/scene.rs | 18 +++++++++--------- examples/ray-tracing/scene.rs | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/ray-tracing-auto/scene.rs b/examples/ray-tracing-auto/scene.rs index 019b61e631..1a017a4954 100644 --- a/examples/ray-tracing-auto/scene.rs +++ b/examples/ray-tracing-auto/scene.rs @@ -179,7 +179,10 @@ impl Scene { let tlas = unsafe { build_top_level_acceleration_structure( - blas.clone(), + vec![AccelerationStructureInstance { + acceleration_structure_reference: blas.device_address().into(), + ..Default::default() + }], memory_allocator.clone(), command_buffer_allocator.clone(), app.device.clone(), @@ -187,7 +190,7 @@ impl Scene { ) }; - let proj = Mat4::perspective_rh_gl(std::f32::consts::FRAC_PI_2, 4.0 / 3.0, 0.01, 100.0); + let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 4.0 / 3.0, 0.01, 100.0); let view = Mat4::look_at_rh( Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, 0.0, 0.0), @@ -436,16 +439,13 @@ unsafe fn build_acceleration_structure_triangles( } unsafe fn build_top_level_acceleration_structure( - acceleration_structure: Arc, + as_instances: Vec, allocator: Arc, command_buffer_allocator: Arc, device: Arc, queue: Arc, ) -> Arc { - let as_instance = AccelerationStructureInstance { - acceleration_structure_reference: acceleration_structure.device_address().into(), - ..Default::default() - }; + let primitive_count = as_instances.len() as u32; let instance_buffer = Buffer::from_iter( allocator.clone(), @@ -459,7 +459,7 @@ unsafe fn build_top_level_acceleration_structure( | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, ..Default::default() }, - [as_instance], + as_instances, ) .unwrap(); @@ -471,7 +471,7 @@ unsafe fn build_top_level_acceleration_structure( build_acceleration_structure_common( geometries, - 1, + primitive_count, AccelerationStructureType::TopLevel, allocator, command_buffer_allocator, diff --git a/examples/ray-tracing/scene.rs b/examples/ray-tracing/scene.rs index b01eec3ed0..9271eb8145 100644 --- a/examples/ray-tracing/scene.rs +++ b/examples/ray-tracing/scene.rs @@ -176,7 +176,10 @@ impl SceneTask { let tlas = unsafe { build_top_level_acceleration_structure( - blas.clone(), + vec![AccelerationStructureInstance { + acceleration_structure_reference: blas.device_address().into(), + ..Default::default() + }], memory_allocator.clone(), command_buffer_allocator.clone(), app.device.clone(), @@ -184,7 +187,7 @@ impl SceneTask { ) }; - let proj = Mat4::perspective_rh_gl(std::f32::consts::FRAC_PI_2, 4.0 / 3.0, 0.01, 100.0); + let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 4.0 / 3.0, 0.01, 100.0); let view = Mat4::look_at_rh( Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, 0.0, 0.0), @@ -454,16 +457,13 @@ unsafe fn build_acceleration_structure_triangles( } unsafe fn build_top_level_acceleration_structure( - acceleration_structure: Arc, + as_instances: Vec, allocator: Arc, command_buffer_allocator: Arc, device: Arc, queue: Arc, ) -> Arc { - let as_instance = AccelerationStructureInstance { - acceleration_structure_reference: acceleration_structure.device_address().into(), - ..Default::default() - }; + let primitive_count = as_instances.len() as u32; let instance_buffer = Buffer::from_iter( allocator.clone(), @@ -477,7 +477,7 @@ unsafe fn build_top_level_acceleration_structure( | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, ..Default::default() }, - [as_instance], + as_instances, ) .unwrap(); @@ -489,7 +489,7 @@ unsafe fn build_top_level_acceleration_structure( build_acceleration_structure_common( geometries, - 1, + primitive_count, AccelerationStructureType::TopLevel, allocator, command_buffer_allocator, From 3faf7df4d96eec8cbc686af7d3bccc43817c0977 Mon Sep 17 00:00:00 2001 From: ComfyFluffy <24245520+ComfyFluffy@users.noreply.github.com> Date: Wed, 29 Jan 2025 15:01:49 +0800 Subject: [PATCH 3/3] buffer alignment --- vulkano/src/pipeline/ray_tracing.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/vulkano/src/pipeline/ray_tracing.rs b/vulkano/src/pipeline/ray_tracing.rs index c4d27a7471..7095f02638 100644 --- a/vulkano/src/pipeline/ray_tracing.rs +++ b/vulkano/src/pipeline/ray_tracing.rs @@ -43,16 +43,18 @@ use super::{ PipelineShaderStageCreateInfoFields1Vk, PipelineShaderStageCreateInfoFields2Vk, }; use crate::{ - buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer}, + buffer::{AllocateBufferError, Buffer, BufferCreateInfo, BufferUsage, Subbuffer}, device::{Device, DeviceOwned, DeviceOwnedDebugWrapper}, instance::InstanceOwnedDebugWrapper, macros::impl_id_counter, memory::{ - allocator::{align_up, AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter}, + allocator::{ + align_up, AllocationCreateInfo, DeviceLayout, MemoryAllocator, MemoryTypeFilter, + }, DeviceAlignment, }, shader::{spirv::ExecutionModel, DescriptorBindingRequirements}, - StridedDeviceAddressRegion, Validated, ValidationError, VulkanError, VulkanObject, + DeviceSize, StridedDeviceAddressRegion, Validated, ValidationError, VulkanError, VulkanObject, }; use foldhash::{HashMap, HashSet}; use smallvec::SmallVec; @@ -921,7 +923,7 @@ impl ShaderBindingTable { device_address: 0, }; - let sbt_buffer = Buffer::new_slice::( + let sbt_buffer = new_bytes_buffer_with_alignment( allocator, BufferCreateInfo { usage: BufferUsage::TRANSFER_SRC @@ -935,6 +937,7 @@ impl ShaderBindingTable { ..Default::default() }, raygen.size + miss.size + hit.size + callable.size, + shader_group_base_alignment, ) .expect("todo: raytracing: better error type for buffer errors"); @@ -976,3 +979,20 @@ impl ShaderBindingTable { }) } } + +fn new_bytes_buffer_with_alignment( + allocator: Arc, + create_info: BufferCreateInfo, + allocation_info: AllocationCreateInfo, + size: DeviceSize, + alignment: DeviceAlignment, +) -> Result, Validated> { + let layout = DeviceLayout::from_size_alignment(size, alignment.as_devicesize()).unwrap(); + let buffer = Subbuffer::new(Buffer::new( + allocator, + create_info, + allocation_info, + layout, + )?); + Ok(buffer) +}