Add limits for acceleration structures (#7845)

This commit is contained in:
Vecvec 2025-06-26 06:49:55 +12:00 committed by GitHub
parent 9d14871f01
commit dc0d457a9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 354 additions and 16 deletions

View File

@ -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

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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 {

View File

@ -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")),

View File

@ -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);

View File

@ -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")),

View File

@ -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,
);
}

View File

@ -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,

View File

@ -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")),

View File

@ -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) {

View File

@ -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(())
}

View File

@ -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::<hal::AccelerationStructureTriangles<dyn hal::DynBuffer>>::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::<dyn hal::DynBuffer> {
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)

View File

@ -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<VertexFormat>),
#[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.

View File

@ -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(

View File

@ -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();

View File

@ -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(),

View File

@ -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

View File

@ -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,
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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,
}
}