diff --git a/CHANGELOG.md b/CHANGELOG.md index c4fbdd466..f5602caf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ Bottom level categories: - Add support for astc-sliced-3d feature. By @mehmetoguzderin in [#7577](https://github.com/gfx-rs/wgpu/issues/7577) - Add support for rendering to slices of 3D texture views and single layered 2D-Array texture views (this requires `VK_KHR_maintenance1` which should be widely available on newer drivers). By @teoxoy in [#7596](https://github.com/gfx-rs/wgpu/pull/7596) - Add extra acceleration structure vertex formats. By @Vecvec in [#7580](https://github.com/gfx-rs/wgpu/pull/7580). +- Add acceleration structure limits. By @Vecvec in [#7845](https://github.com/gfx-rs/wgpu/pull/7845). - Add support for clip-distances feature for Vulkan and GL backends. By @dzamkov in [#7730](https://github.com/gfx-rs/wgpu/pull/7730) #### Naga diff --git a/examples/features/src/ray_cube_compute/mod.rs b/examples/features/src/ray_cube_compute/mod.rs index 45c69819d..1f049a34b 100644 --- a/examples/features/src/ray_cube_compute/mod.rs +++ b/examples/features/src/ray_cube_compute/mod.rs @@ -156,7 +156,7 @@ impl crate::framework::Example for Example { } fn required_limits() -> wgpu::Limits { - wgpu::Limits::default() + wgpu::Limits::default().using_minimum_supported_acceleration_structure_values() } fn init( diff --git a/examples/features/src/ray_cube_fragment/mod.rs b/examples/features/src/ray_cube_fragment/mod.rs index 3f14ba04c..5c6b2d79e 100644 --- a/examples/features/src/ray_cube_fragment/mod.rs +++ b/examples/features/src/ray_cube_fragment/mod.rs @@ -119,7 +119,7 @@ impl crate::framework::Example for Example { } fn required_limits() -> wgpu::Limits { - wgpu::Limits::default() + wgpu::Limits::default().using_minimum_supported_acceleration_structure_values() } fn init( diff --git a/examples/features/src/ray_cube_normals/mod.rs b/examples/features/src/ray_cube_normals/mod.rs index cf35bff34..72985c3b8 100644 --- a/examples/features/src/ray_cube_normals/mod.rs +++ b/examples/features/src/ray_cube_normals/mod.rs @@ -146,7 +146,7 @@ impl crate::framework::Example for Example { } fn required_limits() -> wgpu::Limits { - wgpu::Limits::default() + wgpu::Limits::default().using_minimum_supported_acceleration_structure_values() } fn init( diff --git a/examples/features/src/ray_scene/mod.rs b/examples/features/src/ray_scene/mod.rs index c0e1f4e4d..6db996e12 100644 --- a/examples/features/src/ray_scene/mod.rs +++ b/examples/features/src/ray_scene/mod.rs @@ -329,7 +329,7 @@ impl crate::framework::Example for Example { } fn required_limits() -> wgpu::Limits { - wgpu::Limits::default() + wgpu::Limits::default().using_minimum_supported_acceleration_structure_values() } fn init( diff --git a/examples/features/src/ray_shadows/mod.rs b/examples/features/src/ray_shadows/mod.rs index 453f18849..271db01f9 100644 --- a/examples/features/src/ray_shadows/mod.rs +++ b/examples/features/src/ray_shadows/mod.rs @@ -121,6 +121,7 @@ impl crate::framework::Example for Example { max_push_constant_size: 12, ..wgpu::Limits::default() } + .using_minimum_supported_acceleration_structure_values() } fn init( diff --git a/examples/features/src/ray_traced_triangle/mod.rs b/examples/features/src/ray_traced_triangle/mod.rs index 42a624a31..cd0df2c8e 100644 --- a/examples/features/src/ray_traced_triangle/mod.rs +++ b/examples/features/src/ray_traced_triangle/mod.rs @@ -34,7 +34,7 @@ impl crate::framework::Example for Example { } fn required_limits() -> wgpu::Limits { - wgpu::Limits::default() + wgpu::Limits::default().using_minimum_supported_acceleration_structure_values() } fn required_downlevel_capabilities() -> wgpu::DownlevelCapabilities { diff --git a/tests/tests/wgpu-gpu/ray_tracing/as_build.rs b/tests/tests/wgpu-gpu/ray_tracing/as_build.rs index 30bce6d87..3ef6e7be2 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/as_build.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/as_build.rs @@ -1,6 +1,6 @@ use std::iter; -use crate::ray_tracing::AsBuildContext; +use crate::ray_tracing::{acceleration_structure_limits, AsBuildContext}; use wgpu::util::{BufferInitDescriptor, DeviceExt}; use wgpu::*; use wgpu_test::{ @@ -12,6 +12,7 @@ static UNBUILT_BLAS: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -46,6 +47,7 @@ static UNBUILT_BLAS_COMPACTION: GpuTestConfiguration = GpuTestConfiguration::new .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -74,6 +76,7 @@ static BLAS_COMPACTION_WITHOUT_FLAGS: GpuTestConfiguration = GpuTestConfiguratio .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -110,6 +113,7 @@ static UNPREPARED_BLAS_COMPACTION: GpuTestConfiguration = GpuTestConfiguration:: .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -139,6 +143,7 @@ static BLAS_COMPACTION: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -197,6 +202,7 @@ static OUT_OF_ORDER_AS_BUILD: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -280,6 +286,7 @@ static OUT_OF_ORDER_AS_BUILD_USE: GpuTestConfiguration = GpuTestConfiguration::n .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features( wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE | wgpu::Features::EXPERIMENTAL_RAY_QUERY, @@ -466,6 +473,7 @@ static EMPTY_BUILD: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE), ) .run_sync(empty_build); @@ -486,6 +494,7 @@ static BUILD_WITH_TRANSFORM: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -572,6 +581,7 @@ static ONLY_BLAS_VERTEX_RETURN: GpuTestConfiguration = GpuTestConfiguration::new .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features( wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE | wgpu::Features::EXPERIMENTAL_RAY_QUERY @@ -698,6 +708,7 @@ static ONLY_TLAS_VERTEX_RETURN: GpuTestConfiguration = GpuTestConfiguration::new .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features( wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE | wgpu::Features::EXPERIMENTAL_RAY_QUERY @@ -739,6 +750,7 @@ static EXTRA_FORMAT_BUILD: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features( wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE | wgpu::Features::EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS, @@ -753,6 +765,7 @@ static MISALIGNED_BUILD: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -765,6 +778,7 @@ static TOO_SMALL_STRIDE_BUILD: GpuTestConfiguration = GpuTestConfiguration::new( .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), diff --git a/tests/tests/wgpu-gpu/ray_tracing/as_create.rs b/tests/tests/wgpu-gpu/ray_tracing/as_create.rs index 64459fabf..f6f2e57c3 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/as_create.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/as_create.rs @@ -1,3 +1,4 @@ +use crate::ray_tracing::acceleration_structure_limits; use wgpu::{ AccelerationStructureFlags, AccelerationStructureGeometryFlags, AccelerationStructureUpdateMode, BlasGeometrySizeDescriptors, @@ -12,6 +13,7 @@ static BLAS_INVALID_VERTEX_FORMAT: GpuTestConfiguration = GpuTestConfiguration:: .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE), ) .run_sync(invalid_vertex_format_blas_create); @@ -52,6 +54,7 @@ static BLAS_MISMATCHED_INDEX: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE), ) .run_sync(mismatched_index_blas_create); 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 2ff59f253..3e9c5a45e 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 @@ -1,3 +1,4 @@ +use crate::ray_tracing::acceleration_structure_limits; use std::{iter, mem}; use wgpu::{ include_wgsl, @@ -145,6 +146,7 @@ static ACCELERATION_STRUCTURE_USE_AFTER_FREE: GpuTestConfiguration = GpuTestConf .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(required_features()) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), diff --git a/tests/tests/wgpu-gpu/ray_tracing/limits.rs b/tests/tests/wgpu-gpu/ray_tracing/limits.rs new file mode 100644 index 000000000..a31f5d050 --- /dev/null +++ b/tests/tests/wgpu-gpu/ray_tracing/limits.rs @@ -0,0 +1,120 @@ +use wgpu::wgt::{ + AccelerationStructureFlags, AccelerationStructureGeometryFlags, + AccelerationStructureUpdateMode, BlasGeometrySizeDescriptors, +}; +use wgpu::{ + BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, + BlasTriangleGeometrySizeDescriptor, CreateBlasDescriptor, CreateTlasDescriptor, Limits, + ShaderStages, VertexFormat, +}; +use wgpu_macros::gpu_test; +use wgpu_test::{fail, FailureCase, GpuTestConfiguration, TestParameters, TestingContext}; + +#[gpu_test] +static LIMITS_HIT: GpuTestConfiguration = GpuTestConfiguration::new() + .parameters( + TestParameters::default() + .test_features_limits() + .limits(Limits { + max_blas_primitive_count: 3, + max_blas_geometry_count: 1, + max_tlas_instance_count: 1, + max_acceleration_structures_per_shader_stage: 1, + ..Limits::default() + }) + .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) + // https://github.com/gfx-rs/wgpu/issues/6727 + .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), + ) + .run_sync(hit_limits); + +fn hit_limits(ctx: TestingContext) { + fail( + &ctx.device, + || { + let _ = ctx.device.create_blas( + &CreateBlasDescriptor { + label: None, + flags: AccelerationStructureFlags::PREFER_FAST_TRACE, + update_mode: AccelerationStructureUpdateMode::Build, + }, + BlasGeometrySizeDescriptors::Triangles { + descriptors: vec![ + BlasTriangleGeometrySizeDescriptor { + vertex_format: VertexFormat::Float32x3, + vertex_count: 3, + index_format: None, + index_count: None, + flags: AccelerationStructureGeometryFlags::empty(), + }; + 2 + ], + }, + ); + }, + None, + ); + fail( + &ctx.device, + || { + let _ = ctx.device.create_blas( + &CreateBlasDescriptor { + label: None, + flags: AccelerationStructureFlags::PREFER_FAST_TRACE, + update_mode: AccelerationStructureUpdateMode::Build, + }, + BlasGeometrySizeDescriptors::Triangles { + descriptors: vec![BlasTriangleGeometrySizeDescriptor { + vertex_format: VertexFormat::Float32x3, + vertex_count: 6, + index_format: None, + index_count: None, + flags: AccelerationStructureGeometryFlags::empty(), + }], + }, + ); + }, + None, + ); + fail( + &ctx.device, + || { + let _ = ctx.device.create_tlas(&CreateTlasDescriptor { + label: None, + max_instances: 2, + flags: AccelerationStructureFlags::PREFER_FAST_TRACE, + update_mode: AccelerationStructureUpdateMode::Build, + }); + }, + None, + ); + fail( + &ctx.device, + || { + let _ = ctx + .device + .create_bind_group_layout(&BindGroupLayoutDescriptor { + label: None, + entries: &[ + BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStages::COMPUTE, + ty: BindingType::AccelerationStructure { + vertex_return: false, + }, + count: None, + }, + BindGroupLayoutEntry { + binding: 1, + visibility: ShaderStages::COMPUTE, + ty: BindingType::AccelerationStructure { + vertex_return: false, + }, + count: None, + }, + ], + }); + }, + None, + ); +} diff --git a/tests/tests/wgpu-gpu/ray_tracing/mod.rs b/tests/tests/wgpu-gpu/ray_tracing/mod.rs index 1d7c3a2c3..b72b3466c 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/mod.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/mod.rs @@ -14,9 +14,14 @@ use wgpu_test::TestingContext; mod as_build; mod as_create; mod as_use_after_free; +mod limits; mod scene; mod shader; +fn acceleration_structure_limits() -> wgpu::Limits { + wgpu::Limits::default().using_minimum_supported_acceleration_structure_values() +} + pub struct AsBuildContext { vertices: Buffer, blas_size: BlasTriangleGeometrySizeDescriptor, diff --git a/tests/tests/wgpu-gpu/ray_tracing/scene/mod.rs b/tests/tests/wgpu-gpu/ray_tracing/scene/mod.rs index c8fa6dbd5..11be74bdf 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/scene/mod.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/scene/mod.rs @@ -4,6 +4,7 @@ use wgpu_test::{gpu_test, FailureCase, GpuTestConfiguration, TestParameters, Tes use wgpu::util::DeviceExt; +use crate::ray_tracing::acceleration_structure_limits; use glam::{Affine3A, Quat, Vec3}; mod mesh_gen; @@ -101,6 +102,7 @@ static ACCELERATION_STRUCTURE_BUILD_NO_INDEX: GpuTestConfiguration = GpuTestConf .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), @@ -114,6 +116,7 @@ static ACCELERATION_STRUCTURE_BUILD_WITH_INDEX: GpuTestConfiguration = GpuTestCo .parameters( TestParameters::default() .test_features_limits() + .limits(acceleration_structure_limits()) .features(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) // https://github.com/gfx-rs/wgpu/issues/6727 .skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")), diff --git a/tests/tests/wgpu-gpu/ray_tracing/shader.rs b/tests/tests/wgpu-gpu/ray_tracing/shader.rs index cdda72a40..1ed167e4f 100644 --- a/tests/tests/wgpu-gpu/ray_tracing/shader.rs +++ b/tests/tests/wgpu-gpu/ray_tracing/shader.rs @@ -1,4 +1,4 @@ -use crate::ray_tracing::AsBuildContext; +use crate::ray_tracing::{acceleration_structure_limits, AsBuildContext}; use wgpu::{ include_wgsl, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferDescriptor, CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, @@ -11,10 +11,15 @@ const STRUCT_SIZE: wgpu::BufferAddress = 176; #[gpu_test] static ACCESS_ALL_STRUCT_MEMBERS: GpuTestConfiguration = GpuTestConfiguration::new() - .parameters(TestParameters::default().test_features_limits().features( - wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE - | wgpu::Features::EXPERIMENTAL_RAY_QUERY, - )) + .parameters( + TestParameters::default() + .test_features_limits() + .limits(acceleration_structure_limits()) + .features( + wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE + | wgpu::Features::EXPERIMENTAL_RAY_QUERY, + ), + ) .run_sync(access_all_struct_members); fn access_all_struct_members(ctx: TestingContext) { diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index 6d99ef2f1..d20ec8b10 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -238,6 +238,7 @@ pub enum BindingTypeMaxCountErrorKind { UniformBuffers, BindingArrayElements, BindingArraySamplerElements, + AccelerationStructures, } impl BindingTypeMaxCountErrorKind { @@ -264,6 +265,9 @@ impl BindingTypeMaxCountErrorKind { BindingTypeMaxCountErrorKind::BindingArraySamplerElements => { "max_binding_array_sampler_elements_per_shader_stage" } + BindingTypeMaxCountErrorKind::AccelerationStructures => { + "max_acceleration_structures_per_shader_stage" + } } } } @@ -467,6 +471,10 @@ impl BindingTypeMaxCountValidator { limits.max_binding_array_sampler_elements_per_shader_stage, BindingTypeMaxCountErrorKind::BindingArraySamplerElements, )?; + self.acceleration_structures.validate( + limits.max_acceleration_structures_per_shader_stage, + BindingTypeMaxCountErrorKind::AccelerationStructures, + )?; Ok(()) } diff --git a/wgpu-core/src/device/ray_tracing.rs b/wgpu-core/src/device/ray_tracing.rs index 4e5583370..09f6867da 100644 --- a/wgpu-core/src/device/ray_tracing.rs +++ b/wgpu-core/src/device/ray_tracing.rs @@ -41,6 +41,13 @@ impl Device { let size_info = match &sizes { wgt::BlasGeometrySizeDescriptors::Triangles { descriptors } => { + if descriptors.len() as u32 > self.limits.max_blas_geometry_count { + return Err(CreateBlasError::TooManyGeometries( + self.limits.max_blas_geometry_count, + descriptors.len() as u32, + )); + } + let mut entries = Vec::>::with_capacity( descriptors.len(), @@ -82,6 +89,13 @@ impl Device { }) } + if desc.vertex_count > self.limits.max_blas_primitive_count { + return Err(CreateBlasError::TooManyPrimitives( + self.limits.max_blas_primitive_count, + desc.vertex_count, + )); + } + entries.push(hal::AccelerationStructureTriangles:: { vertex_buffer: None, vertex_format: desc.vertex_format, @@ -164,6 +178,13 @@ impl Device { self.check_is_valid()?; self.require_features(Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE)?; + if desc.max_instances > self.limits.max_tlas_instance_count { + return Err(CreateTlasError::TooManyInstances( + self.limits.max_tlas_instance_count, + desc.max_instances, + )); + } + if desc .flags .contains(wgt::AccelerationStructureFlags::USE_TRANSFORM) diff --git a/wgpu-core/src/ray_tracing.rs b/wgpu-core/src/ray_tracing.rs index 5b952b3be..805e058c2 100644 --- a/wgpu-core/src/ray_tracing.rs +++ b/wgpu-core/src/ray_tracing.rs @@ -35,6 +35,12 @@ pub enum CreateBlasError { MissingIndexData, #[error("Provided format was not within allowed formats. Provided format: {0:?}. Allowed formats: {1:?}")] InvalidVertexFormat(VertexFormat, Vec), + #[error("Limit `max_blas_geometry_count` is {0}, but the BLAS had {1} geometries")] + TooManyGeometries(u32, u32), + #[error( + "Limit `max_blas_primitive_count` is {0}, but the BLAS had a maximum of {1} primitives" + )] + TooManyPrimitives(u32, u32), } #[derive(Clone, Debug, Error)] @@ -45,6 +51,8 @@ pub enum CreateTlasError { MissingFeatures(#[from] MissingFeatures), #[error("Flag {0:?} is not allowed on a TLAS")] DisallowedFlag(wgt::AccelerationStructureFlags), + #[error("Limit `max_tlas_instance_count` is {0}, but the TLAS had a maximum of {1} instances")] + TooManyInstances(u32, u32), } /// Error encountered while attempting to do a copy on a command encoder. diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 472742cef..ae3478b09 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -511,6 +511,21 @@ impl super::Adapter { let max_color_attachment_bytes_per_sample = max_color_attachments * wgt::TextureFormat::MAX_TARGET_PIXEL_BYTE_COST; + let max_srv_count = match options.ResourceBindingTier { + Direct3D12::D3D12_RESOURCE_BINDING_TIER_1 => 128, + _ => full_heap_count, + }; + + // If we also support acceleration structures these are shared so we must halve it. + // It's unlikely that this affects anything because most devices that support ray tracing + // probably have a higher binding tier than one. + let max_sampled_textures_per_shader_stage = + if !features.contains(wgt::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) { + max_srv_count + } else { + max_srv_count / 2 + }; + Some(crate::ExposedAdapter { adapter: super::Adapter { raw: adapter, @@ -538,10 +553,7 @@ impl super::Adapter { .max_dynamic_uniform_buffers_per_pipeline_layout, max_dynamic_storage_buffers_per_pipeline_layout: base .max_dynamic_storage_buffers_per_pipeline_layout, - max_sampled_textures_per_shader_stage: match options.ResourceBindingTier { - Direct3D12::D3D12_RESOURCE_BINDING_TIER_1 => 128, - _ => full_heap_count, - }, + max_sampled_textures_per_shader_stage, max_samplers_per_shader_stage: match options.ResourceBindingTier { Direct3D12::D3D12_RESOURCE_BINDING_TIER_1 => 16, _ => Direct3D12::D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE, @@ -604,6 +616,34 @@ impl super::Adapter { // store buffer sizes using 32 bit ints (a situation we have already encountered with vulkan). max_buffer_size: i32::MAX as u64, max_non_sampler_bindings: 1_000_000, + max_blas_primitive_count: if features + .contains(wgt::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) + { + 1 << 29 // 2^29 + } else { + 0 + }, + max_blas_geometry_count: if features + .contains(wgt::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) + { + 1 << 24 // 2^24 + } else { + 0 + }, + max_tlas_instance_count: if features + .contains(wgt::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) + { + 1 << 24 // 2^24 + } else { + 0 + }, + max_acceleration_structures_per_shader_stage: if features + .contains(wgt::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) + { + max_srv_count / 2 + } else { + 0 + }, }, alignments: crate::Alignments { buffer_copy_offset: wgt::BufferSize::new( diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index ced977ebf..e97968f94 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -801,6 +801,10 @@ impl super::Adapter { max_compute_workgroups_per_dimension, max_buffer_size: i32::MAX as u64, max_non_sampler_bindings: u32::MAX, + max_blas_primitive_count: 0, + max_blas_geometry_count: 0, + max_tlas_instance_count: 0, + max_acceleration_structures_per_shader_stage: 0, }; let mut workarounds = super::Workarounds::empty(); diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index c84ca554c..e15bcd82a 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -1060,6 +1060,16 @@ impl super::PrivateCapabilities { max_compute_workgroups_per_dimension: 0xFFFF, max_buffer_size: self.max_buffer_size, max_non_sampler_bindings: u32::MAX, + max_blas_primitive_count: 0, // When added: 2^28 from https://developer.apple.com/documentation/metal/mtlaccelerationstructureusage/extendedlimits + max_blas_geometry_count: 0, // When added: 2^24 + max_tlas_instance_count: 0, // When added: 2^24 + // Unsure what this will be when added: acceleration structures count as a buffer so + // it may be worth using argument buffers for this all acceleration structures, then + // there will be no limit. + // From 2.17.7 in https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf + // > [Acceleration structures] are opaque objects that can be bound directly using + // buffer binding points or via argument buffers + max_acceleration_structures_per_shader_stage: 0, }, alignments: crate::Alignments { buffer_copy_offset: wgt::BufferSize::new(self.buffer_alignment).unwrap(), diff --git a/wgpu-hal/src/noop/mod.rs b/wgpu-hal/src/noop/mod.rs index d0192cb51..6ae4adcf2 100644 --- a/wgpu-hal/src/noop/mod.rs +++ b/wgpu-hal/src/noop/mod.rs @@ -177,6 +177,10 @@ const CAPABILITIES: crate::Capabilities = { max_subgroup_size: ALLOC_MAX_U32, max_push_constant_size: ALLOC_MAX_U32, max_non_sampler_bindings: ALLOC_MAX_U32, + max_blas_primitive_count: ALLOC_MAX_U32, + max_blas_geometry_count: ALLOC_MAX_U32, + max_tlas_instance_count: ALLOC_MAX_U32, + max_acceleration_structures_per_shader_stage: ALLOC_MAX_U32, }, alignments: crate::Alignments { // All maximally permissive diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index acd32ff6e..406fcc9d4 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -1204,6 +1204,18 @@ impl PhysicalDeviceProperties { let max_color_attachment_bytes_per_sample = limits.max_color_attachments * wgt::TextureFormat::MAX_TARGET_PIXEL_BYTE_COST; + let mut max_blas_geometry_count = 0; + let mut max_blas_primitive_count = 0; + let mut max_tlas_instance_count = 0; + let mut max_acceleration_structures_per_shader_stage = 0; + if let Some(properties) = self.acceleration_structure { + max_blas_geometry_count = properties.max_geometry_count as u32; + max_blas_primitive_count = properties.max_primitive_count as u32; + max_tlas_instance_count = properties.max_instance_count as u32; + max_acceleration_structures_per_shader_stage = + properties.max_per_stage_descriptor_acceleration_structures; + } + wgt::Limits { max_texture_dimension_1d: limits.max_image_dimension1_d, max_texture_dimension_2d: limits.max_image_dimension2_d, @@ -1261,6 +1273,10 @@ impl PhysicalDeviceProperties { max_compute_workgroups_per_dimension, max_buffer_size, max_non_sampler_bindings: u32::MAX, + max_blas_primitive_count, + max_blas_geometry_count, + max_tlas_instance_count, + max_acceleration_structures_per_shader_stage, } } diff --git a/wgpu-info/src/human.rs b/wgpu-info/src/human.rs index 1c2f7a841..d56cc324d 100644 --- a/wgpu-info/src/human.rs +++ b/wgpu-info/src/human.rs @@ -160,6 +160,10 @@ fn print_adapter(output: &mut impl io::Write, report: &AdapterReport, idx: usize max_subgroup_size, max_push_constant_size, max_non_sampler_bindings, + max_blas_primitive_count, + max_blas_geometry_count, + max_tlas_instance_count, + max_acceleration_structures_per_shader_stage, } = limits; writeln!(output, "\t\t Max Texture Dimension 1d: {max_texture_dimension_1d}")?; writeln!(output, "\t\t Max Texture Dimension 2d: {max_texture_dimension_2d}")?; @@ -196,7 +200,10 @@ fn print_adapter(output: &mut impl io::Write, report: &AdapterReport, idx: usize writeln!(output, "\t\t Max Compute Workgroup Size Y: {max_compute_workgroup_size_y}")?; writeln!(output, "\t\t Max Compute Workgroup Size Z: {max_compute_workgroup_size_z}")?; writeln!(output, "\t\t Max Compute Workgroups Per Dimension: {max_compute_workgroups_per_dimension}")?; - + writeln!(output, "\t\t Max BLAS Primitive count: {max_blas_primitive_count}")?; + writeln!(output, "\t\t Max BLAS Geometry count: {max_blas_geometry_count}")?; + writeln!(output, "\t\t Max TLAS Instance count: {max_tlas_instance_count}")?; + writeln!(output, "\t\t Max Acceleration Structures Per Shader Stage: {max_acceleration_structures_per_shader_stage}")?; // This one reflects more of a wgpu implementation limitations than a hardware limit // so don't show it here. let _ = max_non_sampler_bindings; diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 3ba3bbe26..18180f0a6 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -606,6 +606,22 @@ pub struct Limits { /// This limit only affects the d3d12 backend. Using a large number will allow the device /// to create many bind groups at the cost of a large up-front allocation at device creation. pub max_non_sampler_bindings: u32, + /// The maximum number of primitive (ex: triangles, aabbs) a BLAS is allowed to have. Requesting + /// more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`] + /// is enabled. + pub max_blas_primitive_count: u32, + /// The maximum number of geometry descriptors a BLAS is allowed to have. Requesting + /// more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`] + /// is enabled. + pub max_blas_geometry_count: u32, + /// The maximum number of instances a TLAS is allowed to have. Requesting more than 0 during + /// device creation only makes sense if [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`] + /// is enabled. + pub max_tlas_instance_count: u32, + /// The maximum number of acceleration structures allowed to be used in a shader stage. + /// Requesting more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`] + /// is enabled. + pub max_acceleration_structures_per_shader_stage: u32, } impl Default for Limits { @@ -658,6 +674,10 @@ impl Limits { /// max_subgroup_size: 0, /// max_push_constant_size: 0, /// max_non_sampler_bindings: 1_000_000, + /// max_blas_primitive_count: 0, + /// max_blas_geometry_count: 0, + /// max_tlas_instance_count: 0, + /// max_acceleration_structures_per_shader_stage: 0, /// }); /// ``` /// @@ -702,6 +722,10 @@ impl Limits { max_subgroup_size: 0, max_push_constant_size: 0, max_non_sampler_bindings: 1_000_000, + max_blas_primitive_count: 0, + max_blas_geometry_count: 0, + max_tlas_instance_count: 0, + max_acceleration_structures_per_shader_stage: 0, } } @@ -747,6 +771,10 @@ impl Limits { /// max_compute_workgroups_per_dimension: 65535, /// max_buffer_size: 256 << 20, // (256 MiB) /// max_non_sampler_bindings: 1_000_000, + /// max_blas_primitive_count: 0, + /// max_blas_geometry_count: 0, + /// max_tlas_instance_count: 0, + /// max_acceleration_structures_per_shader_stage: 0, /// }); /// ``` #[must_use] @@ -807,6 +835,10 @@ impl Limits { /// max_compute_workgroups_per_dimension: 0, // + /// max_buffer_size: 256 << 20, // (256 MiB), /// max_non_sampler_bindings: 1_000_000, + /// max_blas_primitive_count: 0, + /// max_blas_geometry_count: 0, + /// max_tlas_instance_count: 0, + /// max_acceleration_structures_per_shader_stage: 0, /// }); /// ``` #[must_use] @@ -862,6 +894,32 @@ impl Limits { } } + /// The minimum guaranteed limits for acceleration structures if you enable [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`] + #[must_use] + pub const fn using_minimum_supported_acceleration_structure_values(self) -> Self { + Self { + max_blas_geometry_count: (1 << 24) - 1, // 2^24 - 1: Vulkan's minimum + max_tlas_instance_count: (1 << 24) - 1, // 2^24 - 1: Vulkan's minimum + max_blas_primitive_count: 1 << 28, // 2^28: Metal's minimum + max_acceleration_structures_per_shader_stage: 16, // Vulkan's minimum + ..self + } + } + + /// Modify the current limits to use the acceleration structure limits of `other` (`other` could + /// be the limits of the adapter). + #[must_use] + pub const fn using_acceleration_structure_values(self, other: Self) -> Self { + Self { + max_blas_geometry_count: other.max_blas_geometry_count, + max_tlas_instance_count: other.max_tlas_instance_count, + max_blas_primitive_count: other.max_blas_primitive_count, + max_acceleration_structures_per_shader_stage: other + .max_acceleration_structures_per_shader_stage, + ..self + } + } + /// Compares every limits within self is within the limits given in `allowed`. /// /// If you need detailed information on failures, look at [`Limits::check_limits_with_fail_fn`]. @@ -941,6 +999,9 @@ impl Limits { } compare!(max_push_constant_size, Less); compare!(max_non_sampler_bindings, Less); + compare!(max_blas_primitive_count, Less); + compare!(max_blas_geometry_count, Less); + compare!(max_tlas_instance_count, Less); } } diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index a6ff408ae..3189d99cf 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -827,6 +827,11 @@ fn map_wgt_limits(limits: webgpu_sys::GpuSupportedLimits) -> wgt::Limits { max_push_constant_size: wgt::Limits::default().max_push_constant_size, max_non_sampler_bindings: wgt::Limits::default().max_non_sampler_bindings, max_inter_stage_shader_components: wgt::Limits::default().max_inter_stage_shader_components, + max_blas_primitive_count: wgt::Limits::default().max_blas_primitive_count, + max_blas_geometry_count: wgt::Limits::default().max_blas_geometry_count, + max_tlas_instance_count: wgt::Limits::default().max_tlas_instance_count, + max_acceleration_structures_per_shader_stage: wgt::Limits::default() + .max_acceleration_structures_per_shader_stage, } }