Skip to content

Add extra acceleration structure vertex formats. #7580

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,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).

#### Naga

Expand Down
203 changes: 202 additions & 1 deletion tests/tests/wgpu-gpu/ray_tracing/as_build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::iter;
use std::{iter, mem};

use crate::ray_tracing::AsBuildContext;
use wgpu::util::{BufferInitDescriptor, DeviceExt};
Expand Down Expand Up @@ -604,3 +604,204 @@ fn only_tlas_vertex_return(ctx: TestingContext) {
None,
);
}

#[gpu_test]
static EXTRA_FORMAT_BUILD: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.test_features_limits()
.features(
wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE
| wgpu::Features::EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS,
)
// https://github.com/gfx-rs/wgpu/issues/6727
.skip(FailureCase::backend_adapter(wgpu::Backends::VULKAN, "AMD")),
)
.run_sync(extra_format_build);

fn extra_format_build(ctx: TestingContext) {
let vertices = ctx.device.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: &[0; mem::size_of::<[[i16; 3]; 3]>()],
usage: BufferUsages::BLAS_INPUT,
});

let blas_size = BlasTriangleGeometrySizeDescriptor {
// The fourth component is ignored, and it allows us to have a smaller stride.
vertex_format: VertexFormat::Snorm16x4,
vertex_count: 3,
index_format: None,
index_count: None,
flags: wgpu::AccelerationStructureGeometryFlags::empty(),
};

let blas = ctx.device.create_blas(
&CreateBlasDescriptor {
label: Some("BLAS"),
flags: wgpu::AccelerationStructureFlags::PREFER_FAST_TRACE,
update_mode: AccelerationStructureUpdateMode::Build,
},
BlasGeometrySizeDescriptors::Triangles {
descriptors: vec![blas_size.clone()],
},
);

let mut command_encoder = ctx
.device
.create_command_encoder(&CommandEncoderDescriptor {
label: Some("BLAS_1"),
});
command_encoder.build_acceleration_structures(
&[BlasBuildEntry {
blas: &blas,
geometry: BlasGeometries::TriangleGeometries(vec![BlasTriangleGeometry {
size: &blas_size,
vertex_buffer: &vertices,
first_vertex: 0,
vertex_stride: mem::size_of::<[i16; 3]>() as BufferAddress,
index_buffer: None,
first_index: None,
transform_buffer: None,
transform_buffer_offset: None,
}]),
}],
&[],
);
ctx.queue.submit([command_encoder.finish()]);
}

#[gpu_test]
static MISALIGNED_BUILD: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.test_features_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")),
)
.run_sync(misaligned_build);

fn misaligned_build(ctx: TestingContext) {
let vertices = ctx.device.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: &[0; mem::size_of::<[[i16; 3]; 3]>()],
usage: BufferUsages::BLAS_INPUT,
});

let blas_size = BlasTriangleGeometrySizeDescriptor {
// The fourth component is ignored, and it allows us to have a smaller stride.
vertex_format: VertexFormat::Float32x3,
vertex_count: 3,
index_format: None,
index_count: None,
flags: wgpu::AccelerationStructureGeometryFlags::empty(),
};

let blas = ctx.device.create_blas(
&CreateBlasDescriptor {
label: Some("BLAS"),
flags: wgpu::AccelerationStructureFlags::PREFER_FAST_TRACE,
update_mode: AccelerationStructureUpdateMode::Build,
},
BlasGeometrySizeDescriptors::Triangles {
descriptors: vec![blas_size.clone()],
},
);

let mut command_encoder = ctx
.device
.create_command_encoder(&CommandEncoderDescriptor {
label: Some("BLAS_1"),
});
fail(
&ctx.device,
|| {
command_encoder.build_acceleration_structures(
&[BlasBuildEntry {
blas: &blas,
geometry: BlasGeometries::TriangleGeometries(vec![BlasTriangleGeometry {
size: &blas_size,
vertex_buffer: &vertices,
first_vertex: 0,
// Not aligned to four bytes like it should be
vertex_stride: 13,
index_buffer: None,
first_index: None,
transform_buffer: None,
transform_buffer_offset: None,
}]),
}],
&[],
)
},
None,
);
}

#[gpu_test]
static TOO_SMALL_STRIDE_BUILD: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.test_features_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")),
)
.run_sync(too_small_stride_build);

fn too_small_stride_build(ctx: TestingContext) {
let vertices = ctx.device.create_buffer_init(&BufferInitDescriptor {
label: None,
contents: &[0; mem::size_of::<[[i16; 3]; 3]>()],
usage: BufferUsages::BLAS_INPUT,
});

let blas_size = BlasTriangleGeometrySizeDescriptor {
// The fourth component is ignored, and it allows us to have a smaller stride.
vertex_format: VertexFormat::Float32x3,
vertex_count: 3,
index_format: None,
index_count: None,
flags: wgpu::AccelerationStructureGeometryFlags::empty(),
};

let blas = ctx.device.create_blas(
&CreateBlasDescriptor {
label: Some("BLAS"),
flags: wgpu::AccelerationStructureFlags::PREFER_FAST_TRACE,
update_mode: AccelerationStructureUpdateMode::Build,
},
BlasGeometrySizeDescriptors::Triangles {
descriptors: vec![blas_size.clone()],
},
);

let mut command_encoder = ctx
.device
.create_command_encoder(&CommandEncoderDescriptor {
label: Some("BLAS_1"),
});
fail(
&ctx.device,
|| {
command_encoder.build_acceleration_structures(
&[BlasBuildEntry {
blas: &blas,
geometry: BlasGeometries::TriangleGeometries(vec![BlasTriangleGeometry {
size: &blas_size,
vertex_buffer: &vertices,
first_vertex: 0,
// Aligned to four bytes but too small
vertex_stride: 8,
index_buffer: None,
first_index: None,
transform_buffer: None,
transform_buffer_offset: None,
}]),
}],
&[],
)
},
None,
);
}
29 changes: 29 additions & 0 deletions wgpu-core/src/command/ray_tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,35 @@ fn iter_blas<'a>(
));
}

if size_desc
.vertex_format
.acceleration_structure_vertex_readable_size()
> mesh.vertex_stride
{
return Err(BuildAccelerationStructureError::VertexStrideTooSmall(
blas.error_ident(),
size_desc
.vertex_format
.acceleration_structure_vertex_readable_size(),
mesh.vertex_stride,
));
}

if mesh.vertex_stride
% size_desc
.vertex_format
.acceleration_structure_stride_alignment()
!= 0
{
return Err(BuildAccelerationStructureError::VertexStrideUnaligned(
blas.error_ident(),
size_desc
.vertex_format
.acceleration_structure_stride_alignment(),
mesh.vertex_stride,
));
}

match (size_desc.index_count, mesh.size.index_count) {
(Some(_), None) | (None, Some(_)) => {
return Err(
Expand Down
6 changes: 6 additions & 0 deletions wgpu-core/src/ray_tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ pub enum BuildAccelerationStructureError {
#[error("Blas {0:?} vertex formats are different, creation format: {1:?}, provided: {2:?}")]
DifferentBlasVertexFormats(ResourceErrorIdent, VertexFormat, VertexFormat),

#[error("Blas {0:?} stride was required to be at least {1} but stride given was {2}")]
VertexStrideTooSmall(ResourceErrorIdent, u64, u64),

#[error("Blas {0:?} stride was required to be a multiple of {1} but stride given was {2}")]
VertexStrideUnaligned(ResourceErrorIdent, u64, u64),

#[error("Blas {0:?} index count was provided at creation or building, but not the other")]
BlasIndexCountProvidedMismatch(ResourceErrorIdent),

Expand Down
3 changes: 2 additions & 1 deletion wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,8 @@ impl super::Adapter {
// Once ray tracing pipelines are supported they also will go here
features.set(
wgt::Features::EXPERIMENTAL_RAY_QUERY
| wgt::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE,
| wgt::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE
| wgt::Features::EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS,
features5.RaytracingTier == Direct3D12::D3D12_RAYTRACING_TIER_1_1
&& shader_model >= naga::back::hlsl::ShaderModel::V6_5
&& has_features5,
Expand Down
3 changes: 2 additions & 1 deletion wgpu-hal/src/vulkan/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,8 @@ impl PhysicalDeviceFeatures {
features.set(F::DEPTH32FLOAT_STENCIL8, texture_d32_s8);

features.set(
F::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE,
F::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE
| F::EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS,
caps.supports_extension(khr::deferred_host_operations::NAME)
&& caps.supports_extension(khr::acceleration_structure::NAME)
&& caps.supports_extension(khr::buffer_device_address::NAME),
Expand Down
16 changes: 16 additions & 0 deletions wgpu-types/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,15 @@ bitflags_array! {
///
/// This is a native only feature.
const EXPERIMENTAL_MESH_SHADER_MULTIVIEW = 1 << 49;

/// Allows usage of additional vertex formats in [BlasTriangleGeometrySizeDescriptor::vertex_format]
///
/// Supported platforms
/// - Vulkan
/// - DX12
///
/// [BlasTriangleGeometrySizeDescriptor::vertex_format]: super::BlasTriangleGeometrySizeDescriptor
const EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS = 1 << 50;
}

/// Features that are not guaranteed to be supported.
Expand Down Expand Up @@ -1463,6 +1472,13 @@ impl Features {
if self.contains(Self::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) {
formats.push(VertexFormat::Float32x3);
}
if self.contains(Self::EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS) {
formats.push(VertexFormat::Float32x2);
formats.push(VertexFormat::Float16x2);
formats.push(VertexFormat::Float16x4);
formats.push(VertexFormat::Snorm16x2);
formats.push(VertexFormat::Snorm16x4);
}
formats
}
}
Expand Down
25 changes: 24 additions & 1 deletion wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4974,6 +4974,29 @@ impl VertexFormat {
Self::Float64x4 => 32,
}
}

/// Returns the readable size of the vertex format in and acceleration structure build (this is
/// slightly different from [`Self::size`])
#[must_use]
pub const fn acceleration_structure_vertex_readable_size(&self) -> u64 {
match self {
Self::Float16x2 | Self::Snorm16x2 => 4,
Self::Float32x3 => 12,
Self::Float32x2 => 8,
Self::Float16x4 | Self::Snorm16x4 => 6,
_ => unreachable!(),
}
}

/// Returns the alignment required for `wgpu::BlasTriangleGeometry::vertex_stride`
#[must_use]
pub const fn acceleration_structure_stride_alignment(&self) -> u64 {
match self {
Self::Float16x4 | Self::Float16x2 | Self::Snorm16x4 | Self::Snorm16x2 => 2,
Self::Float32x2 | Self::Float32x3 => 4,
_ => unreachable!(),
}
}
}

bitflags::bitflags! {
Expand Down Expand Up @@ -7434,7 +7457,7 @@ impl Default for ShaderRuntimeChecks {
pub struct BlasTriangleGeometrySizeDescriptor {
/// Format of a vertex position, must be [`VertexFormat::Float32x3`]
/// with just [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`]
/// but later features may add more formats.
/// but [`Features::EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS`] adds more.
pub vertex_format: VertexFormat,
/// Number of vertices.
pub vertex_count: u32,
Expand Down
3 changes: 2 additions & 1 deletion wgpu/src/api/blas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ pub struct BlasTriangleGeometry<'a> {
pub vertex_buffer: &'a Buffer,
/// Offset into the vertex buffer as a factor of the vertex stride.
pub first_vertex: u32,
/// Vertex stride.
/// Vertex stride, must be greater than [`wgpu_types::VertexFormat::acceleration_structure_vertex_readable_size`]
/// of the format and must be a multiple of [`wgpu_types::VertexFormat::acceleration_structure_stride_alignment`].
pub vertex_stride: wgt::BufferAddress,
/// Index buffer (optional).
pub index_buffer: Option<&'a Buffer>,
Expand Down
Loading