diff --git a/CHANGELOG.md b/CHANGELOG.md index b92c3f02df..5a7f1c4f10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,8 @@ Naga now infers the correct binding layout when a resource appears only in an as #### General - Removed `MaintainBase` in favor of using `PollType`. By @waywardmonkeys in [#7508](https://github.com/gfx-rs/wgpu/pull/7508). +- Remove `CommandEncoder::build_acceleration_structures_unsafe_tlas` in favour of `as_hal` and apply + simplifications allowed by this. By @Vecvec in [#7513](https://github.com/gfx-rs/wgpu/pull/7513) #### Naga diff --git a/docs/api-specs/ray_tracing.md b/docs/api-specs/ray_tracing.md index 9d56cf1a6f..c843d5fe60 100644 --- a/docs/api-specs/ray_tracing.md +++ b/docs/api-specs/ray_tracing.md @@ -21,9 +21,7 @@ can be found with their definitions. A [`Blas`] can be created with [`Device::create_blas`]. A [`Tlas`] can be created with [`Device::create_tlas`]. -Unless one is planning on using the unsafe building API (not recommended for beginners) a [`Tlas`] should be put inside -a [`TlasPackage`]. After that a reference to the [`Tlas`] can be retrieved by calling [`TlasPackage::tlas`]. -This reference can be placed in a bind group to be used in a shader. A reference to a [`Blas`] can +The [`Tlas`] reference can be placed in a bind group to be used in a shader. A reference to a [`Blas`] can be used to create [`TlasInstance`] alongside a transformation matrix, a custom index (this can be any data that should be given to the shader on a hit) which only the first 24 bits may be set, and a mask to filter hits in the shader. @@ -39,8 +37,6 @@ Before a [`Tlas`] is used in a shader it must [`Tlas`]: https://wgpu.rs/doc/wgpu/struct.Tlas.html [`Blas`]: https://wgpu.rs/doc/wgpu/struct.Blas.html [`TlasInstance`]: https://wgpu.rs/doc/wgpu/struct.TlasInstance.html -[`TlasPackage`]: https://wgpu.rs/doc/wgpu/struct.TlasPackage.html -[`TlasPackage::tlas`]: https://wgpu.rs/doc/wgpu/struct.TlasPackage.html#method.tlas ## `naga`'s raytracing API: diff --git a/examples/features/src/ray_cube_compute/mod.rs b/examples/features/src/ray_cube_compute/mod.rs index 10493390a3..3c1c784fa7 100644 --- a/examples/features/src/ray_cube_compute/mod.rs +++ b/examples/features/src/ray_cube_compute/mod.rs @@ -130,7 +130,7 @@ struct Example { vertex_buf: wgpu::Buffer, #[expect(dead_code)] index_buf: wgpu::Buffer, - tlas_package: wgpu::TlasPackage, + tlas: wgpu::Tlas, compute_pipeline: wgpu::ComputePipeline, compute_bind_group: wgpu::BindGroup, blit_pipeline: wgpu::RenderPipeline, @@ -257,7 +257,7 @@ impl crate::framework::Example for Example { }, ); - let tlas = device.create_tlas(&wgpu::CreateTlasDescriptor { + let mut tlas = device.create_tlas(&wgpu::CreateTlasDescriptor { label: None, flags: wgpu::AccelerationStructureFlags::PREFER_FAST_TRACE, update_mode: wgpu::AccelerationStructureUpdateMode::Build, @@ -346,13 +346,11 @@ impl crate::framework::Example for Example { ], }); - let mut tlas_package = wgpu::TlasPackage::new(tlas); - let dist = 3.0; for x in 0..side_count { for y in 0..side_count { - tlas_package[(x + y * side_count) as usize] = Some(wgpu::TlasInstance::new( + tlas[(x + y * side_count) as usize] = Some(wgpu::TlasInstance::new( &blas, affine_to_rows(&Affine3A::from_rotation_translation( Quat::from_rotation_y(45.9_f32.to_radians()), @@ -387,7 +385,7 @@ impl crate::framework::Example for Example { }, ]), }), - iter::once(&tlas_package), + iter::once(&tlas), ); queue.submit(Some(encoder.finish())); @@ -401,7 +399,7 @@ impl crate::framework::Example for Example { uniform_buf, vertex_buf, index_buf, - tlas_package, + tlas, compute_pipeline, compute_bind_group, blit_pipeline, @@ -427,7 +425,7 @@ impl crate::framework::Example for Example { let anim_time = self.start_inst.elapsed().as_secs_f64() as f32; - self.tlas_package[0].as_mut().unwrap().transform = + self.tlas[0].as_mut().unwrap().transform = affine_to_rows(&Affine3A::from_rotation_translation( Quat::from_euler( glam::EulerRot::XYZ, @@ -445,7 +443,7 @@ impl crate::framework::Example for Example { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); - encoder.build_acceleration_structures(iter::empty(), iter::once(&self.tlas_package)); + encoder.build_acceleration_structures(iter::empty(), iter::once(&self.tlas)); { let mut cpass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { diff --git a/examples/features/src/ray_cube_fragment/mod.rs b/examples/features/src/ray_cube_fragment/mod.rs index 96be61c3b7..0e5d79cac2 100644 --- a/examples/features/src/ray_cube_fragment/mod.rs +++ b/examples/features/src/ray_cube_fragment/mod.rs @@ -98,7 +98,7 @@ struct Example { uniforms: Uniforms, uniform_buf: wgpu::Buffer, blas: wgpu::Blas, - tlas_package: wgpu::TlasPackage, + tlas: wgpu::Tlas, pipeline: wgpu::RenderPipeline, bind_group: wgpu::BindGroup, start_inst: Instant, @@ -237,8 +237,6 @@ impl crate::framework::Example for Example { ], }); - let tlas_package = wgpu::TlasPackage::new(tlas); - let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); @@ -259,7 +257,7 @@ impl crate::framework::Example for Example { ]), }), // iter::empty(), - iter::once(&tlas_package), + iter::once(&tlas), ); queue.submit(Some(encoder.finish())); @@ -270,7 +268,7 @@ impl crate::framework::Example for Example { uniforms, uniform_buf, blas, - tlas_package, + tlas, pipeline, bind_group, start_inst, @@ -310,7 +308,7 @@ impl crate::framework::Example for Example { for x in 0..side_count { for y in 0..side_count { - let instance = self.tlas_package.index_mut((x + y * side_count) as usize); + let instance = self.tlas.index_mut((x + y * side_count) as usize); let x = x as f32 / (side_count - 1) as f32; let y = y as f32 / (side_count - 1) as f32; @@ -342,7 +340,7 @@ impl crate::framework::Example for Example { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); - encoder.build_acceleration_structures(iter::empty(), iter::once(&self.tlas_package)); + encoder.build_acceleration_structures(iter::empty(), iter::once(&self.tlas)); { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { diff --git a/examples/features/src/ray_cube_normals/mod.rs b/examples/features/src/ray_cube_normals/mod.rs index 5b80e5c04d..cbb368931d 100644 --- a/examples/features/src/ray_cube_normals/mod.rs +++ b/examples/features/src/ray_cube_normals/mod.rs @@ -120,7 +120,7 @@ impl>> Future for ErrorFuture { struct Example { rt_target: wgpu::Texture, - tlas_package: wgpu::TlasPackage, + tlas: wgpu::Tlas, compute_pipeline: wgpu::ComputePipeline, compute_bind_group: wgpu::BindGroup, blit_pipeline: wgpu::RenderPipeline, @@ -249,7 +249,7 @@ impl crate::framework::Example for Example { }, ); - let tlas = device.create_tlas(&wgpu::CreateTlasDescriptor { + let mut tlas = device.create_tlas(&wgpu::CreateTlasDescriptor { label: None, flags: wgpu::AccelerationStructureFlags::PREFER_FAST_TRACE | wgpu::AccelerationStructureFlags::ALLOW_RAY_HIT_VERTEX_RETURN, @@ -339,13 +339,11 @@ impl crate::framework::Example for Example { ], }); - let mut tlas_package = wgpu::TlasPackage::new(tlas); - let dist = 3.0; for x in 0..side_count { for y in 0..side_count { - tlas_package[(x + y * side_count) as usize] = Some(wgpu::TlasInstance::new( + tlas[(x + y * side_count) as usize] = Some(wgpu::TlasInstance::new( &blas, affine_to_rows(&Affine3A::from_rotation_translation( Quat::from_rotation_y(45.9_f32.to_radians()), @@ -380,7 +378,7 @@ impl crate::framework::Example for Example { }, ]), }), - iter::once(&tlas_package), + iter::once(&tlas), ); queue.submit(Some(encoder.finish())); @@ -389,7 +387,7 @@ impl crate::framework::Example for Example { Example { rt_target, - tlas_package, + tlas, compute_pipeline, compute_bind_group, blit_pipeline, @@ -415,7 +413,7 @@ impl crate::framework::Example for Example { let anim_time = self.start_inst.elapsed().as_secs_f64() as f32; - self.tlas_package[0].as_mut().unwrap().transform = + self.tlas[0].as_mut().unwrap().transform = affine_to_rows(&Affine3A::from_rotation_translation( Quat::from_euler( glam::EulerRot::XYZ, @@ -433,7 +431,7 @@ impl crate::framework::Example for Example { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); - encoder.build_acceleration_structures(iter::empty(), iter::once(&self.tlas_package)); + encoder.build_acceleration_structures(iter::empty(), iter::once(&self.tlas)); { let mut cpass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { diff --git a/examples/features/src/ray_scene/mod.rs b/examples/features/src/ray_scene/mod.rs index a4a4548172..a52d9f0532 100644 --- a/examples/features/src/ray_scene/mod.rs +++ b/examples/features/src/ray_scene/mod.rs @@ -307,7 +307,7 @@ fn load_scene(device: &wgpu::Device, queue: &wgpu::Queue) -> SceneComponents { struct Example { uniforms: Uniforms, uniform_buf: wgpu::Buffer, - tlas_package: wgpu::TlasPackage, + tlas: wgpu::Tlas, pipeline: wgpu::RenderPipeline, bind_group: wgpu::BindGroup, start_inst: Instant, @@ -369,8 +369,6 @@ impl crate::framework::Example for Example { max_instances: side_count * side_count, }); - let tlas_package = wgpu::TlasPackage::new(tlas); - let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { label: None, source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))), @@ -413,7 +411,7 @@ impl crate::framework::Example for Example { }, wgpu::BindGroupEntry { binding: 5, - resource: tlas_package.as_binding(), + resource: tlas.as_binding(), }, wgpu::BindGroupEntry { binding: 1, @@ -439,7 +437,7 @@ impl crate::framework::Example for Example { Example { uniforms, uniform_buf, - tlas_package, + tlas, pipeline, bind_group, start_inst, @@ -480,7 +478,7 @@ impl crate::framework::Example for Example { for x in 0..side_count { for y in 0..side_count { - let instance = self.tlas_package.index_mut(x + y * side_count); + let instance = self.tlas.index_mut(x + y * side_count); let blas_index = (x + y) % self @@ -522,7 +520,7 @@ impl crate::framework::Example for Example { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); - encoder.build_acceleration_structures(iter::empty(), iter::once(&self.tlas_package)); + encoder.build_acceleration_structures(iter::empty(), iter::once(&self.tlas)); { let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { diff --git a/examples/features/src/ray_shadows/mod.rs b/examples/features/src/ray_shadows/mod.rs index 2054632aef..32a3a95644 100644 --- a/examples/features/src/ray_shadows/mod.rs +++ b/examples/features/src/ray_shadows/mod.rs @@ -168,7 +168,7 @@ impl crate::framework::Example for Example { }, ); - let tlas = device.create_tlas(&wgpu::CreateTlasDescriptor { + let mut tlas = device.create_tlas(&wgpu::CreateTlasDescriptor { label: None, flags: wgpu::AccelerationStructureFlags::PREFER_FAST_TRACE, update_mode: wgpu::AccelerationStructureUpdateMode::Build, @@ -242,9 +242,7 @@ impl crate::framework::Example for Example { cache: None, }); - let mut tlas_package = wgpu::TlasPackage::new(tlas); - - tlas_package[0] = Some(wgpu::TlasInstance::new( + tlas[0] = Some(wgpu::TlasInstance::new( &blas, [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0], 0, @@ -270,7 +268,7 @@ impl crate::framework::Example for Example { }, ]), }), - iter::once(&tlas_package), + iter::once(&tlas), ); queue.submit(Some(encoder.finish())); @@ -285,7 +283,7 @@ impl crate::framework::Example for Example { }, wgpu::BindGroupEntry { binding: 1, - resource: tlas_package.as_binding(), + resource: tlas.as_binding(), }, ], }); diff --git a/examples/features/src/ray_traced_triangle/mod.rs b/examples/features/src/ray_traced_triangle/mod.rs index 85e1f88518..5890f066f6 100644 --- a/examples/features/src/ray_traced_triangle/mod.rs +++ b/examples/features/src/ray_traced_triangle/mod.rs @@ -6,11 +6,11 @@ use wgpu::{include_wgsl, BufferUsages, IndexFormat, SamplerDescriptor}; use wgpu::{ AccelerationStructureFlags, AccelerationStructureUpdateMode, BlasBuildEntry, BlasGeometries, BlasGeometrySizeDescriptors, BlasTriangleGeometry, BlasTriangleGeometrySizeDescriptor, - CreateBlasDescriptor, CreateTlasDescriptor, TlasInstance, TlasPackage, + CreateBlasDescriptor, CreateTlasDescriptor, Tlas, TlasInstance, }; struct Example { - tlas_package: TlasPackage, + tlas: Tlas, compute_pipeline: wgpu::ComputePipeline, blit_pipeline: wgpu::RenderPipeline, bind_group: wgpu::BindGroup, @@ -145,16 +145,14 @@ impl crate::framework::Example for Example { }, ); - let tlas = device.create_tlas(&CreateTlasDescriptor { + let mut tlas = device.create_tlas(&CreateTlasDescriptor { label: None, max_instances: 3, flags: AccelerationStructureFlags::PREFER_FAST_TRACE, update_mode: AccelerationStructureUpdateMode::Build, }); - let mut tlas_package = TlasPackage::new(tlas); - - tlas_package[0] = Some(TlasInstance::new( + tlas[0] = Some(TlasInstance::new( &blas, Mat4::from_translation(Vec3 { x: 0.0, @@ -169,7 +167,7 @@ impl crate::framework::Example for Example { 0xff, )); - tlas_package[1] = Some(TlasInstance::new( + tlas[1] = Some(TlasInstance::new( &blas, Mat4::from_translation(Vec3 { x: -1.0, @@ -184,7 +182,7 @@ impl crate::framework::Example for Example { 0xff, )); - tlas_package[2] = Some(TlasInstance::new( + tlas[2] = Some(TlasInstance::new( &blas, Mat4::from_translation(Vec3 { x: 1.0, @@ -232,7 +230,7 @@ impl crate::framework::Example for Example { transform_buffer_offset: None, }]), }), - Some(&tlas_package), + Some(&tlas), ); queue.submit(Some(encoder.finish())); @@ -331,7 +329,7 @@ impl crate::framework::Example for Example { }, wgpu::BindGroupEntry { binding: 2, - resource: wgpu::BindingResource::AccelerationStructure(tlas_package.tlas()), + resource: wgpu::BindingResource::AccelerationStructure(&tlas), }, ], }); @@ -354,7 +352,7 @@ impl crate::framework::Example for Example { }); Self { - tlas_package, + tlas, compute_pipeline, blit_pipeline, bind_group, @@ -375,7 +373,7 @@ impl crate::framework::Example for Example { fn update(&mut self, _event: winit::event::WindowEvent) {} fn render(&mut self, view: &wgpu::TextureView, device: &wgpu::Device, queue: &wgpu::Queue) { - self.tlas_package[0].as_mut().unwrap().transform = + self.tlas[0].as_mut().unwrap().transform = Mat4::from_rotation_y(self.start.elapsed().as_secs_f32()) .transpose() .to_cols_array()[..12] @@ -385,7 +383,7 @@ impl crate::framework::Example for Example { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); - encoder.build_acceleration_structures(None, Some(&self.tlas_package)); + encoder.build_acceleration_structures(None, Some(&self.tlas)); { let mut cpass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { diff --git a/player/src/lib.rs b/player/src/lib.rs index b1934036ba..53bcdab50f 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -122,44 +122,6 @@ impl GlobalPlay for wgc::global::Global { ) .unwrap(); } - trace::Command::BuildAccelerationStructuresUnsafeTlas { blas, tlas } => { - let blas_iter = blas.iter().map(|x| { - let geometries = match &x.geometries { - wgc::ray_tracing::TraceBlasGeometries::TriangleGeometries( - triangle_geometries, - ) => { - let iter = triangle_geometries.iter().map(|tg| { - wgc::ray_tracing::BlasTriangleGeometry { - size: &tg.size, - vertex_buffer: tg.vertex_buffer, - index_buffer: tg.index_buffer, - transform_buffer: tg.transform_buffer, - first_vertex: tg.first_vertex, - vertex_stride: tg.vertex_stride, - first_index: tg.first_index, - transform_buffer_offset: tg.transform_buffer_offset, - } - }); - wgc::ray_tracing::BlasGeometries::TriangleGeometries(Box::new(iter)) - } - }; - wgc::ray_tracing::BlasBuildEntry { - blas_id: x.blas_id, - geometries, - } - }); - - if !tlas.is_empty() { - log::error!("a trace of command_encoder_build_acceleration_structures_unsafe_tlas containing a tlas build is not replayable! skipping tlas build"); - } - - self.command_encoder_build_acceleration_structures_unsafe_tlas( - encoder, - blas_iter, - std::iter::empty(), - ) - .unwrap(); - } trace::Command::BuildAccelerationStructures { blas, tlas } => { let blas_iter = blas.iter().map(|x| { let geometries = match &x.geometries { diff --git a/tests/tests/wgpu-gpu/ray_tracing/as_build.rs b/tests/tests/wgpu-gpu/ray_tracing/as_build.rs index f7e72daf9d..c9b8ad95d6 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/as_build.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/as_build.rs @@ -30,7 +30,7 @@ fn unbuilt_blas(ctx: TestingContext) { .device .create_command_encoder(&CommandEncoderDescriptor::default()); - encoder.build_acceleration_structures([], [&as_ctx.tlas_package]); + encoder.build_acceleration_structures([], [&as_ctx.tlas]); fail( &ctx.device, @@ -69,7 +69,7 @@ fn out_of_order_as_build(ctx: TestingContext) { label: Some("TLAS 1"), }); - encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas_package]); + encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas]); let mut encoder_blas = ctx .device @@ -112,7 +112,7 @@ fn out_of_order_as_build(ctx: TestingContext) { label: Some("TLAS 2"), }); - encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas_package]); + encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas]); fail( &ctx.device, @@ -167,7 +167,7 @@ fn out_of_order_as_build_use(ctx: TestingContext) { label: Some("TLAS 1"), }); - encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas_package]); + encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas]); let mut encoder_blas2 = ctx .device @@ -206,7 +206,7 @@ fn out_of_order_as_build_use(ctx: TestingContext) { layout: &compute_pipeline.get_bind_group_layout(0), entries: &[BindGroupEntry { binding: 0, - resource: BindingResource::AccelerationStructure(as_ctx.tlas_package.tlas()), + resource: BindingResource::AccelerationStructure(&as_ctx.tlas), }], }); @@ -267,7 +267,7 @@ fn out_of_order_as_build_use(ctx: TestingContext) { label: Some("TLAS 2"), }); - encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas_package]); + encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas]); ctx.queue.submit([ encoder_blas.finish(), @@ -280,7 +280,7 @@ fn out_of_order_as_build_use(ctx: TestingContext) { layout: &compute_pipeline.get_bind_group_layout(0), entries: &[BindGroupEntry { binding: 0, - resource: BindingResource::AccelerationStructure(as_ctx.tlas_package.tlas()), + resource: BindingResource::AccelerationStructure(&as_ctx.tlas), }], }); @@ -327,20 +327,7 @@ fn empty_build(ctx: TestingContext) { encoder_safe.build_acceleration_structures(iter::empty(), iter::empty()); - let mut encoder_unsafe = ctx - .device - .create_command_encoder(&CommandEncoderDescriptor { - label: Some("BLAS 1"), - }); - - // # SAFETY: - // we don't actually do anything so all the requirements are satisfied - unsafe { - encoder_unsafe.build_acceleration_structures_unsafe_tlas(iter::empty(), iter::empty()); - } - - ctx.queue - .submit([encoder_safe.finish(), encoder_unsafe.finish()]); + ctx.queue.submit([encoder_safe.finish()]); } #[gpu_test] @@ -391,15 +378,13 @@ fn build_with_transform(ctx: TestingContext) { }, ); - let tlas = ctx.device.create_tlas(&CreateTlasDescriptor { + let mut tlas = ctx.device.create_tlas(&CreateTlasDescriptor { label: Some("TLAS"), max_instances: 1, flags: AccelerationStructureFlags::PREFER_FAST_TRACE, update_mode: AccelerationStructureUpdateMode::Build, }); - - let mut tlas_package = TlasPackage::new(tlas); - tlas_package[0] = Some(TlasInstance::new( + tlas[0] = Some(TlasInstance::new( &blas, [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0], 0, @@ -426,7 +411,7 @@ fn build_with_transform(ctx: TestingContext) { transform_buffer_offset: Some(0), }]), }], - [&tlas_package], + [&tlas], ); ctx.queue.submit([encoder_build.finish()]); } @@ -468,7 +453,7 @@ fn only_blas_vertex_return(ctx: TestingContext) { label: Some("TLAS 1"), }); - encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas_package]); + encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas]); ctx.queue .submit([encoder_blas.finish(), encoder_tlas.finish()]); @@ -498,9 +483,7 @@ fn only_blas_vertex_return(ctx: TestingContext) { layout: &bind_group_layout, entries: &[BindGroupEntry { binding: 0, - resource: BindingResource::AccelerationStructure( - as_ctx.tlas_package.tlas(), - ), + resource: BindingResource::AccelerationStructure(&as_ctx.tlas), }], }); }, @@ -534,7 +517,7 @@ fn only_blas_vertex_return(ctx: TestingContext) { layout: &compute_pipeline.get_bind_group_layout(0), entries: &[BindGroupEntry { binding: 0, - resource: BindingResource::AccelerationStructure(as_ctx.tlas_package.tlas()), + resource: BindingResource::AccelerationStructure(&as_ctx.tlas), }], }); @@ -599,7 +582,7 @@ fn only_tlas_vertex_return(ctx: TestingContext) { fail( &ctx.device, || { - encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas_package]); + encoder_tlas.build_acceleration_structures([], [&as_ctx.tlas]); }, None, ); diff --git a/tests/tests/wgpu-gpu/ray_tracing/as_use_after_free.rs b/tests/tests/wgpu-gpu/ray_tracing/as_use_after_free.rs index c6ea31a914..2ff59f253b 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/as_use_after_free.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/as_use_after_free.rs @@ -7,7 +7,7 @@ use wgpu::{ BlasBuildEntry, BlasGeometries, BlasGeometrySizeDescriptors, BlasTriangleGeometry, BlasTriangleGeometrySizeDescriptor, BufferAddress, BufferUsages, CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, CreateBlasDescriptor, CreateTlasDescriptor, - PollType, TlasInstance, TlasPackage, VertexFormat, + PollType, TlasInstance, VertexFormat, }; use wgpu_macros::gpu_test; use wgpu_test::{FailureCase, GpuTestConfiguration, TestParameters, TestingContext}; @@ -49,16 +49,14 @@ fn acceleration_structure_use_after_free(ctx: TestingContext) { }, ); // Create the TLAS - let tlas = ctx.device.create_tlas(&CreateTlasDescriptor { + let mut tlas = ctx.device.create_tlas(&CreateTlasDescriptor { label: Some("tlas use after free"), max_instances: 1, flags: AccelerationStructureFlags::PREFER_FAST_TRACE, update_mode: AccelerationStructureUpdateMode::Build, }); - // Put an unbuilt BLAS in the tlas package. - let mut tlas_package = TlasPackage::new(tlas); - tlas_package[0] = Some(TlasInstance::new( + tlas[0] = Some(TlasInstance::new( &blas, [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0], 0, @@ -95,7 +93,7 @@ fn acceleration_structure_use_after_free(ctx: TestingContext) { let mut encoder = ctx .device .create_command_encoder(&CommandEncoderDescriptor::default()); - encoder.build_acceleration_structures(iter::empty(), iter::once(&tlas_package)); + encoder.build_acceleration_structures(iter::empty(), iter::once(&tlas)); ctx.queue.submit(Some(encoder.finish())); // Create a compute shader that uses an AS. @@ -118,12 +116,12 @@ fn acceleration_structure_use_after_free(ctx: TestingContext) { layout: &compute_pipeline.get_bind_group_layout(0), entries: &[BindGroupEntry { binding: 0, - resource: BindingResource::AccelerationStructure(tlas_package.tlas()), + resource: BindingResource::AccelerationStructure(&tlas), }], }); // Drop the TLAS package and ensure that if it was going to die, it is dead. - drop(tlas_package); + drop(tlas); ctx.device.poll(PollType::Wait).unwrap(); // Run the pass with the bind group that references the TLAS package. diff --git a/tests/tests/wgpu-gpu/ray_tracing/mod.rs b/tests/tests/wgpu-gpu/ray_tracing/mod.rs index 10b087496a..1d7c3a2c32 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/mod.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/mod.rs @@ -3,7 +3,7 @@ use wgpu::util::BufferInitDescriptor; use wgpu::{ util::DeviceExt, Blas, BlasBuildEntry, BlasGeometries, BlasGeometrySizeDescriptors, BlasTriangleGeometry, BlasTriangleGeometrySizeDescriptor, Buffer, CreateBlasDescriptor, - CreateTlasDescriptor, TlasInstance, TlasPackage, + CreateTlasDescriptor, Tlas, TlasInstance, }; use wgpu::{ AccelerationStructureFlags, AccelerationStructureGeometryFlags, @@ -22,7 +22,7 @@ pub struct AsBuildContext { blas_size: BlasTriangleGeometrySizeDescriptor, blas: Blas, // Putting this last, forces the BLAS to die before the TLAS. - tlas_package: TlasPackage, + tlas: Tlas, } impl AsBuildContext { @@ -56,15 +56,14 @@ impl AsBuildContext { }, ); - let tlas = ctx.device.create_tlas(&CreateTlasDescriptor { + let mut tlas = ctx.device.create_tlas(&CreateTlasDescriptor { label: Some("TLAS"), max_instances: 1, flags: AccelerationStructureFlags::PREFER_FAST_TRACE | additional_tlas_flags, update_mode: AccelerationStructureUpdateMode::Build, }); - let mut tlas_package = TlasPackage::new(tlas); - tlas_package[0] = Some(TlasInstance::new( + tlas[0] = Some(TlasInstance::new( &blas, [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0], 0, @@ -75,7 +74,7 @@ impl AsBuildContext { vertices, blas_size, blas, - tlas_package, + tlas, } } diff --git a/tests/tests/wgpu-gpu/ray_tracing/scene/mod.rs b/tests/tests/wgpu-gpu/ray_tracing/scene/mod.rs index 85bed25cfd..c8fa6dbd57 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/scene/mod.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/scene/mod.rs @@ -48,17 +48,15 @@ fn acceleration_structure_build(ctx: &TestingContext, use_index_buffer: bool) { }, ); - let tlas = device.create_tlas(&wgpu::CreateTlasDescriptor { + let mut tlas = device.create_tlas(&wgpu::CreateTlasDescriptor { label: None, flags: wgpu::AccelerationStructureFlags::PREFER_FAST_TRACE, update_mode: wgpu::AccelerationStructureUpdateMode::Build, max_instances, }); - let mut tlas_package = wgpu::TlasPackage::new(tlas); - for j in 0..max_instances { - tlas_package[j as usize] = Some(wgpu::TlasInstance::new( + tlas[j as usize] = Some(wgpu::TlasInstance::new( &blas, mesh_gen::affine_to_rows(&Affine3A::from_rotation_translation( Quat::from_rotation_y(45.9_f32.to_radians()), @@ -90,7 +88,7 @@ fn acceleration_structure_build(ctx: &TestingContext, use_index_buffer: bool) { transform_buffer_offset: None, }]), }), - iter::once(&tlas_package), + iter::once(&tlas), ); ctx.queue.submit(Some(encoder.finish())); diff --git a/tests/tests/wgpu-gpu/ray_tracing/shader.rs b/tests/tests/wgpu-gpu/ray_tracing/shader.rs index 851cdc7f3a..cdda72a405 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/shader.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/shader.rs @@ -40,8 +40,7 @@ fn access_all_struct_members(ctx: TestingContext) { label: Some("Build"), }); - encoder_build - .build_acceleration_structures([&as_ctx.blas_build_entry()], [&as_ctx.tlas_package]); + encoder_build.build_acceleration_structures([&as_ctx.blas_build_entry()], [&as_ctx.tlas]); ctx.queue.submit([encoder_build.finish()]); @@ -69,7 +68,7 @@ fn access_all_struct_members(ctx: TestingContext) { entries: &[ BindGroupEntry { binding: 0, - resource: BindingResource::AccelerationStructure(as_ctx.tlas_package.tlas()), + resource: BindingResource::AccelerationStructure(&as_ctx.tlas), }, BindGroupEntry { binding: 1, diff --git a/wgpu-core/src/command/ray_tracing.rs b/wgpu-core/src/command/ray_tracing.rs index a5386934ed..8857af6514 100644 --- a/wgpu-core/src/command/ray_tracing.rs +++ b/wgpu-core/src/command/ray_tracing.rs @@ -19,7 +19,7 @@ use crate::{ init_tracker::MemoryInitKind, ray_tracing::{ BlasBuildEntry, BlasGeometries, BlasTriangleGeometry, BuildAccelerationStructureError, - TlasBuildEntry, TlasInstance, TlasPackage, TraceBlasBuildEntry, TraceBlasGeometries, + TlasInstance, TlasPackage, TraceBlasBuildEntry, TraceBlasGeometries, TraceBlasTriangleGeometry, TraceTlasInstance, TraceTlasPackage, }, resource::{AccelerationStructure, Blas, Buffer, Labeled, StagingBuffer, Tlas}, @@ -56,12 +56,6 @@ struct TlasStore<'a> { range: Range, } -struct TlasBufferStore { - buffer: Arc, - transition: Option>, - entry: TlasBuildEntry, -} - impl Global { pub fn command_encoder_mark_acceleration_structures_built( &self, @@ -106,274 +100,6 @@ impl Global { Ok(()) } - // Currently this function is very similar to its safe counterpart, however certain parts of it are very different, - // making for the two to be implemented differently, the main difference is this function has separate buffers for each - // of the TLAS instances while the other has one large buffer - // TODO: reconsider this function's usefulness once blas and tlas `as_hal` are added and some time has passed. - pub fn command_encoder_build_acceleration_structures_unsafe_tlas<'a>( - &self, - command_encoder_id: CommandEncoderId, - blas_iter: impl Iterator>, - tlas_iter: impl Iterator, - ) -> Result<(), BuildAccelerationStructureError> { - profiling::scope!("CommandEncoder::build_acceleration_structures_unsafe_tlas"); - - let hub = &self.hub; - - let cmd_buf = hub - .command_buffers - .get(command_encoder_id.into_command_buffer_id()); - - let device = &cmd_buf.device; - - device.require_features(Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE)?; - - let mut build_command = AsBuild::default(); - - #[cfg(feature = "trace")] - let trace_blas: Vec = blas_iter - .map(|blas_entry| { - let geometries = match blas_entry.geometries { - BlasGeometries::TriangleGeometries(triangle_geometries) => { - TraceBlasGeometries::TriangleGeometries( - triangle_geometries - .map(|tg| TraceBlasTriangleGeometry { - size: tg.size.clone(), - vertex_buffer: tg.vertex_buffer, - index_buffer: tg.index_buffer, - transform_buffer: tg.transform_buffer, - first_vertex: tg.first_vertex, - vertex_stride: tg.vertex_stride, - first_index: tg.first_index, - transform_buffer_offset: tg.transform_buffer_offset, - }) - .collect(), - ) - } - }; - TraceBlasBuildEntry { - blas_id: blas_entry.blas_id, - geometries, - } - }) - .collect(); - - #[cfg(feature = "trace")] - let trace_tlas: Vec = tlas_iter.collect(); - #[cfg(feature = "trace")] - if let Some(ref mut list) = cmd_buf.data.lock().get_inner()?.commands { - list.push( - crate::device::trace::Command::BuildAccelerationStructuresUnsafeTlas { - blas: trace_blas.clone(), - tlas: trace_tlas.clone(), - }, - ); - if !trace_tlas.is_empty() { - log::warn!("a trace of command_encoder_build_acceleration_structures_unsafe_tlas containing a tlas build is not replayable!"); - } - } - - #[cfg(feature = "trace")] - let blas_iter = trace_blas.iter().map(|blas_entry| { - let geometries = match &blas_entry.geometries { - TraceBlasGeometries::TriangleGeometries(triangle_geometries) => { - let iter = triangle_geometries.iter().map(|tg| BlasTriangleGeometry { - size: &tg.size, - vertex_buffer: tg.vertex_buffer, - index_buffer: tg.index_buffer, - transform_buffer: tg.transform_buffer, - first_vertex: tg.first_vertex, - vertex_stride: tg.vertex_stride, - first_index: tg.first_index, - transform_buffer_offset: tg.transform_buffer_offset, - }); - BlasGeometries::TriangleGeometries(Box::new(iter)) - } - }; - BlasBuildEntry { - blas_id: blas_entry.blas_id, - geometries, - } - }); - - #[cfg(feature = "trace")] - let tlas_iter = trace_tlas.iter(); - - let mut input_barriers = Vec::>::new(); - let mut buf_storage = Vec::new(); - - let mut scratch_buffer_blas_size = 0; - let mut blas_storage = Vec::new(); - let mut cmd_buf_data = cmd_buf.data.lock(); - let mut cmd_buf_data_guard = cmd_buf_data.record()?; - let cmd_buf_data = &mut *cmd_buf_data_guard; - - iter_blas( - blas_iter, - cmd_buf_data, - &mut build_command, - &mut buf_storage, - hub, - )?; - - let snatch_guard = device.snatchable_lock.read(); - iter_buffers( - &mut buf_storage, - &snatch_guard, - &mut input_barriers, - cmd_buf_data, - &mut scratch_buffer_blas_size, - &mut blas_storage, - hub, - device.alignments.ray_tracing_scratch_buffer_alignment, - )?; - - let mut scratch_buffer_tlas_size = 0; - let mut tlas_storage = Vec::::new(); - let mut tlas_buf_storage = Vec::new(); - - for entry in tlas_iter { - let instance_buffer = hub.buffers.get(entry.instance_buffer_id).get()?; - let data = cmd_buf_data.trackers.buffers.set_single( - &instance_buffer, - BufferUses::BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT, - ); - tlas_buf_storage.push(TlasBufferStore { - buffer: instance_buffer, - transition: data, - entry: entry.clone(), - }); - } - - for tlas_buf in &mut tlas_buf_storage { - let entry = &tlas_buf.entry; - let instance_buffer = { - let (instance_buffer, instance_pending) = - (&mut tlas_buf.buffer, &mut tlas_buf.transition); - let instance_raw = instance_buffer.try_raw(&snatch_guard)?; - instance_buffer.check_usage(BufferUsages::TLAS_INPUT)?; - - if let Some(barrier) = instance_pending - .take() - .map(|pending| pending.into_hal(instance_buffer, &snatch_guard)) - { - input_barriers.push(barrier); - } - instance_raw - }; - - let tlas = hub.tlas_s.get(entry.tlas_id).get()?; - cmd_buf_data.trackers.tlas_s.insert_single(tlas.clone()); - - build_command.tlas_s_built.push(TlasBuild { - tlas: tlas.clone(), - dependencies: Vec::new(), - }); - - let scratch_buffer_offset = scratch_buffer_tlas_size; - scratch_buffer_tlas_size += align_to( - tlas.size_info.build_scratch_size as u32, - device.alignments.ray_tracing_scratch_buffer_alignment, - ) as u64; - - tlas_storage.push(UnsafeTlasStore { - tlas, - entries: hal::AccelerationStructureEntries::Instances( - hal::AccelerationStructureInstances { - buffer: Some(instance_buffer), - offset: 0, - count: entry.instance_count, - }, - ), - scratch_buffer_offset, - }); - } - - let scratch_size = - match wgt::BufferSize::new(max(scratch_buffer_blas_size, scratch_buffer_tlas_size)) { - None => { - cmd_buf_data_guard.mark_successful(); - return Ok(()); - } - Some(size) => size, - }; - - let scratch_buffer = ScratchBuffer::new(device, scratch_size)?; - - let scratch_buffer_barrier = hal::BufferBarrier:: { - buffer: scratch_buffer.raw(), - usage: hal::StateTransition { - from: BufferUses::ACCELERATION_STRUCTURE_SCRATCH, - to: BufferUses::ACCELERATION_STRUCTURE_SCRATCH, - }, - }; - - let mut tlas_descriptors = Vec::new(); - - for UnsafeTlasStore { - tlas, - entries, - scratch_buffer_offset, - } in &tlas_storage - { - if tlas.update_mode == wgt::AccelerationStructureUpdateMode::PreferUpdate { - log::info!("only rebuild implemented") - } - tlas_descriptors.push(hal::BuildAccelerationStructureDescriptor { - entries, - mode: hal::AccelerationStructureBuildMode::Build, - flags: tlas.flags, - source_acceleration_structure: None, - destination_acceleration_structure: tlas.try_raw(&snatch_guard)?, - scratch_buffer: scratch_buffer.raw(), - scratch_buffer_offset: *scratch_buffer_offset, - }) - } - - let blas_present = !blas_storage.is_empty(); - let tlas_present = !tlas_storage.is_empty(); - - let cmd_buf_raw = cmd_buf_data.encoder.open()?; - - let mut descriptors = Vec::new(); - - for storage in &blas_storage { - descriptors.push(map_blas(storage, scratch_buffer.raw(), &snatch_guard)?); - } - - build_blas( - cmd_buf_raw, - blas_present, - tlas_present, - input_barriers, - &descriptors, - scratch_buffer_barrier, - ); - - if tlas_present { - unsafe { - cmd_buf_raw.build_acceleration_structures(&tlas_descriptors); - - cmd_buf_raw.place_acceleration_structure_barrier( - hal::AccelerationStructureBarrier { - usage: hal::StateTransition { - from: hal::AccelerationStructureUses::BUILD_OUTPUT, - to: hal::AccelerationStructureUses::SHADER_INPUT, - }, - }, - ); - } - } - - cmd_buf_data - .temp_resources - .push(TempResource::ScratchBuffer(scratch_buffer)); - - cmd_buf_data.as_actions.push(AsAction::Build(build_command)); - - cmd_buf_data_guard.mark_successful(); - Ok(()) - } pub fn command_encoder_build_acceleration_structures<'a>( &self, diff --git a/wgpu-core/src/device/trace.rs b/wgpu-core/src/device/trace.rs index 3932d4086b..a0920b8df5 100644 --- a/wgpu-core/src/device/trace.rs +++ b/wgpu-core/src/device/trace.rs @@ -202,10 +202,6 @@ pub enum Command { timestamp_writes: Option, occlusion_query_set_id: Option, }, - BuildAccelerationStructuresUnsafeTlas { - blas: Vec, - tlas: Vec, - }, BuildAccelerationStructures { blas: Vec, tlas: Vec, diff --git a/wgpu/src/api/blas.rs b/wgpu/src/api/blas.rs index 82c976b98d..0c0d02b753 100644 --- a/wgpu/src/api/blas.rs +++ b/wgpu/src/api/blas.rs @@ -31,7 +31,7 @@ static_assertions::assert_impl_all!(CreateBlasDescriptor<'_>: Send, Sync); /// Safe instance for a [Tlas]. /// -/// A TlasInstance may be made invalid, if a TlasInstance is invalid, any attempt to build a [TlasPackage] containing an +/// A TlasInstance may be made invalid, if a TlasInstance is invalid, any attempt to build a [Tlas] containing an /// invalid TlasInstance will generate a validation error /// /// Each one contains: @@ -42,7 +42,6 @@ static_assertions::assert_impl_all!(CreateBlasDescriptor<'_>: Send, Sync); /// - A user accessible custom index /// /// [Tlas]: crate::Tlas -/// [TlasPackage]: crate::TlasPackage #[derive(Debug, Clone)] pub struct TlasInstance { pub(crate) blas: dispatch::DispatchBlas, diff --git a/wgpu/src/api/command_encoder.rs b/wgpu/src/api/command_encoder.rs index 6e91a45284..d19534e757 100644 --- a/wgpu/src/api/command_encoder.rs +++ b/wgpu/src/api/command_encoder.rs @@ -1,10 +1,7 @@ use core::ops::Range; use crate::{ - api::{ - blas::BlasBuildEntry, - tlas::{TlasBuildEntry, TlasPackage}, - }, + api::{blas::BlasBuildEntry, tlas::Tlas}, *, }; @@ -341,34 +338,12 @@ impl CommandEncoder { pub fn build_acceleration_structures<'a>( &mut self, blas: impl IntoIterator>, - tlas: impl IntoIterator, + tlas: impl IntoIterator, ) { self.inner .build_acceleration_structures(&mut blas.into_iter(), &mut tlas.into_iter()); } - /// Build bottom and top level acceleration structures. - /// See [`CommandEncoder::build_acceleration_structures`] for the safe version and more details. All validation in [`CommandEncoder::build_acceleration_structures`] except that - /// listed under tlas applies here as well. - /// - /// # Safety - /// - /// - The contents of the raw instance buffer must be valid for the underling api. - /// - All bottom level acceleration structures, referenced in the raw instance buffer must be valid and built, - /// when the corresponding top level acceleration structure is built. (builds may happen in the same invocation of this function). - /// - At the time when the top level acceleration structure is used in a bind group, all associated bottom level acceleration structures must be valid, - /// and built (no later than the time when the top level acceleration structure was built). - pub unsafe fn build_acceleration_structures_unsafe_tlas<'a>( - &mut self, - blas: impl IntoIterator>, - tlas: impl IntoIterator>, - ) { - self.inner.build_acceleration_structures_unsafe_tlas( - &mut blas.into_iter(), - &mut tlas.into_iter(), - ); - } - /// Transition resources to an underlying hal resource state. /// /// This is an advanced, native-only API (no-op on web) that has two main use cases: diff --git a/wgpu/src/api/device.rs b/wgpu/src/api/device.rs index 2955f322a7..54dadf9240 100644 --- a/wgpu/src/api/device.rs +++ b/wgpu/src/api/device.rs @@ -1,6 +1,5 @@ -use alloc::{boxed::Box, string::String, sync::Arc}; +use alloc::{boxed::Box, string::String, sync::Arc, vec}; use core::{error, fmt, future::Future}; - use parking_lot::Mutex; use crate::api::blas::{Blas, BlasGeometrySizeDescriptors, CreateBlasDescriptor}; @@ -604,10 +603,9 @@ impl Device { let tlas = self.inner.create_tlas(desc); Tlas { - shared: Arc::new(TlasShared { - inner: tlas, - max_instances: desc.max_instances, - }), + inner: tlas, + instances: vec![None; desc.max_instances as usize], + lowest_unmodified: 0, } } } diff --git a/wgpu/src/api/tlas.rs b/wgpu/src/api/tlas.rs index 3a5e765942..c786e49b09 100644 --- a/wgpu/src/api/tlas.rs +++ b/wgpu/src/api/tlas.rs @@ -1,36 +1,31 @@ -use alloc::{sync::Arc, vec, vec::Vec}; -use core::ops::{Index, IndexMut, Range}; - use crate::{api::blas::TlasInstance, dispatch}; -use crate::{BindingResource, Buffer, Label}; +use crate::{BindingResource, Label}; +use alloc::vec::Vec; +use core::ops::{Index, IndexMut, Range}; use wgt::WasmNotSendSync; /// Descriptor to create top level acceleration structures. pub type CreateTlasDescriptor<'a> = wgt::CreateTlasDescriptor>; static_assertions::assert_impl_all!(CreateTlasDescriptor<'_>: Send, Sync); -#[derive(Debug)] -pub(crate) struct TlasShared { - pub(crate) inner: dispatch::DispatchTlas, - pub(crate) max_instances: u32, -} - #[derive(Debug, Clone)] /// Top Level Acceleration Structure (TLAS). /// /// A TLAS contains a series of [TLAS instances], which are a reference to /// a BLAS and a transformation matrix placing the geometry in the world. /// -/// A TLAS contains TLAS instances in a device readable form, you cant interact +/// A TLAS also contains an extra set of TLAS instances in a device readable form, you cant interact /// directly with these, instead you have to build the TLAS with [TLAS instances]. /// /// [TLAS instances]: TlasInstance pub struct Tlas { - pub(crate) shared: Arc, + pub(crate) inner: dispatch::DispatchTlas, + pub(crate) instances: Vec>, + pub(crate) lowest_unmodified: u32, } static_assertions::assert_impl_all!(Tlas: WasmNotSendSync); -crate::cmp::impl_eq_ord_hash_proxy!(Tlas => .shared.inner); +crate::cmp::impl_eq_ord_hash_proxy!(Tlas => .inner); impl Tlas { /// Returns the inner hal Acceleration Structure using a callback. The hal acceleration structure @@ -51,7 +46,7 @@ impl Tlas { &mut self, hal_tlas_callback: F, ) -> R { - if let Some(tlas) = self.shared.inner.as_core_opt() { + if let Some(tlas) = self.inner.as_core_opt() { unsafe { tlas.context.tlas_as_hal::(tlas, hal_tlas_callback) } } else { hal_tlas_callback(None) @@ -61,47 +56,7 @@ impl Tlas { #[cfg(custom)] /// Returns custom implementation of Tlas (if custom backend and is internally T) pub fn as_custom(&self) -> Option<&T> { - self.shared.inner.as_custom() - } -} - -/// Entry for a top level acceleration structure build. -/// Used with raw instance buffers for an unvalidated builds. -/// See [`TlasPackage`] for the safe version. -pub struct TlasBuildEntry<'a> { - /// Reference to the acceleration structure. - pub tlas: &'a Tlas, - /// Reference to the raw instance buffer, each instance is similar to [`TlasInstance`] but contains a handle to the BLAS. - pub instance_buffer: &'a Buffer, - /// Number of instances in the instance buffer. - pub instance_count: u32, -} -static_assertions::assert_impl_all!(TlasBuildEntry<'_>: WasmNotSendSync); - -/// The safe version of [`TlasBuildEntry`], containing [`TlasInstance`]s instead of a raw buffer. -pub struct TlasPackage { - pub(crate) tlas: Tlas, - pub(crate) instances: Vec>, - pub(crate) lowest_unmodified: u32, -} -static_assertions::assert_impl_all!(TlasPackage: WasmNotSendSync); - -impl TlasPackage { - /// Construct [`TlasPackage`] consuming the [`Tlas`] (prevents modification of the [`Tlas`] without using this package). - pub fn new(tlas: Tlas) -> Self { - let max_instances = tlas.shared.max_instances; - Self::new_with_instances(tlas, vec![None; max_instances as usize]) - } - - /// Construct [`TlasPackage`] consuming the [`Tlas`] (prevents modification of the [`Tlas`] without using this package). - /// This constructor moves the instances into the package (the number of instances needs to fit into tlas, - /// otherwise when building a validation error will be raised). - pub fn new_with_instances(tlas: Tlas, instances: Vec>) -> Self { - Self { - tlas, - lowest_unmodified: instances.len() as u32, - instances, - } + self.inner.as_custom() } /// Get a reference to all instances. @@ -147,16 +102,11 @@ impl TlasPackage { /// /// [`BindGroup`]: super::BindGroup pub fn as_binding(&self) -> BindingResource<'_> { - BindingResource::AccelerationStructure(&self.tlas) - } - - /// Get a reference to the underling [`Tlas`]. - pub fn tlas(&self) -> &Tlas { - &self.tlas + BindingResource::AccelerationStructure(self) } } -impl Index for TlasPackage { +impl Index for Tlas { type Output = Option; fn index(&self, index: usize) -> &Self::Output { @@ -164,7 +114,7 @@ impl Index for TlasPackage { } } -impl Index> for TlasPackage { +impl Index> for Tlas { type Output = [Option]; fn index(&self, index: Range) -> &Self::Output { @@ -172,7 +122,7 @@ impl Index> for TlasPackage { } } -impl IndexMut for TlasPackage { +impl IndexMut for Tlas { fn index_mut(&mut self, index: usize) -> &mut Self::Output { let idx = self.instances.index_mut(index); if index as u32 + 1 > self.lowest_unmodified { @@ -182,7 +132,7 @@ impl IndexMut for TlasPackage { } } -impl IndexMut> for TlasPackage { +impl IndexMut> for Tlas { fn index_mut(&mut self, index: Range) -> &mut Self::Output { let idx = self.instances.index_mut(index.clone()); if index.end > self.lowest_unmodified as usize { diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index bf074a65a3..597107c53e 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -3092,18 +3092,10 @@ impl dispatch::CommandEncoderInterface for WebCommandEncoder { unimplemented!("Raytracing not implemented for web"); } - fn build_acceleration_structures_unsafe_tlas<'a>( - &self, - _blas: &mut dyn Iterator>, - _tlas: &mut dyn Iterator>, - ) { - unimplemented!("Raytracing not implemented for web"); - } - fn build_acceleration_structures<'a>( &self, _blas: &mut dyn Iterator>, - _tlas: &mut dyn Iterator, + _tlas: &mut dyn Iterator, ) { unimplemented!("Raytracing not implemented for web"); } diff --git a/wgpu/src/backend/wgpu_core.rs b/wgpu/src/backend/wgpu_core.rs index 2c28df9fb0..b099846849 100644 --- a/wgpu/src/backend/wgpu_core.rs +++ b/wgpu/src/backend/wgpu_core.rs @@ -1238,7 +1238,7 @@ impl dispatch::DeviceInterface for CoreDevice { } BindingResource::AccelerationStructure(acceleration_structure) => { bm::BindingResource::AccelerationStructure( - acceleration_structure.shared.inner.as_core().id, + acceleration_structure.inner.as_core().id, ) } }, @@ -2548,7 +2548,7 @@ impl dispatch::CommandEncoderInterface for CoreCommandEncoder { .map(|b| b.inner.as_core().id) .collect::>(); let tlas = tlas - .map(|t| t.shared.inner.as_core().id) + .map(|t| t.inner.as_core().id) .collect::>(); if let Err(cause) = self .context @@ -2563,60 +2563,10 @@ impl dispatch::CommandEncoderInterface for CoreCommandEncoder { } } - fn build_acceleration_structures_unsafe_tlas<'a>( - &self, - blas: &mut dyn Iterator>, - tlas: &mut dyn Iterator>, - ) { - let blas = blas.map(|e: &crate::BlasBuildEntry<'_>| { - let geometries = match e.geometry { - crate::BlasGeometries::TriangleGeometries(ref triangle_geometries) => { - let iter = triangle_geometries.iter().map(|tg| { - wgc::ray_tracing::BlasTriangleGeometry { - vertex_buffer: tg.vertex_buffer.inner.as_core().id, - index_buffer: tg.index_buffer.map(|buf| buf.inner.as_core().id), - transform_buffer: tg.transform_buffer.map(|buf| buf.inner.as_core().id), - size: tg.size, - transform_buffer_offset: tg.transform_buffer_offset, - first_vertex: tg.first_vertex, - vertex_stride: tg.vertex_stride, - first_index: tg.first_index, - } - }); - wgc::ray_tracing::BlasGeometries::TriangleGeometries(Box::new(iter)) - } - }; - wgc::ray_tracing::BlasBuildEntry { - blas_id: e.blas.inner.as_core().id, - geometries, - } - }); - - let tlas = tlas.into_iter().map(|e: &crate::TlasBuildEntry<'a>| { - wgc::ray_tracing::TlasBuildEntry { - tlas_id: e.tlas.shared.inner.as_core().id, - instance_buffer_id: e.instance_buffer.inner.as_core().id, - instance_count: e.instance_count, - } - }); - - if let Err(cause) = self - .context - .0 - .command_encoder_build_acceleration_structures_unsafe_tlas(self.id, blas, tlas) - { - self.context.handle_error_nolabel( - &self.error_sink, - cause, - "CommandEncoder::build_acceleration_structures_unsafe_tlas", - ); - } - } - fn build_acceleration_structures<'a>( &self, blas: &mut dyn Iterator>, - tlas: &mut dyn Iterator, + tlas: &mut dyn Iterator, ) { let blas = blas.map(|e: &crate::BlasBuildEntry<'_>| { let geometries = match e.geometry { @@ -2657,7 +2607,7 @@ impl dispatch::CommandEncoderInterface for CoreCommandEncoder { }) }); wgc::ray_tracing::TlasPackage { - tlas_id: e.tlas.shared.inner.as_core().id, + tlas_id: e.inner.as_core().id, instances: Box::new(instances), lowest_unmodified: e.lowest_unmodified, } diff --git a/wgpu/src/dispatch.rs b/wgpu/src/dispatch.rs index 9a606c1be2..b2c3aa6e16 100644 --- a/wgpu/src/dispatch.rs +++ b/wgpu/src/dispatch.rs @@ -331,15 +331,10 @@ pub trait CommandEncoderInterface: CommonTraits { tlas: &mut dyn Iterator, ); - fn build_acceleration_structures_unsafe_tlas<'a>( - &self, - blas: &mut dyn Iterator>, - tlas: &mut dyn Iterator>, - ); fn build_acceleration_structures<'a>( &self, blas: &mut dyn Iterator>, - tlas: &mut dyn Iterator, + tlas: &mut dyn Iterator, ); fn transition_resources<'a>(