wgpu_core/
ray_tracing.rs

1// Ray tracing
2// Major missing optimizations (no api surface changes needed):
3// - use custom tracker to track build state
4// - no forced rebuilt (build mode deduction)
5// - lazy instance buffer allocation
6// - maybe share scratch and instance staging buffer allocation
7// - partial instance buffer uploads (api surface already designed with this in mind)
8// - ([non performance] extract function in build (rust function extraction with guards is a pain))
9
10use crate::{
11    command::CommandEncoderError,
12    device::{DeviceError, MissingFeatures},
13    id::{BlasId, BufferId, TlasId},
14    resource::{DestroyedResourceError, InvalidResourceError, MissingBufferUsageError},
15};
16use std::num::NonZeroU64;
17use std::sync::Arc;
18
19use crate::resource::{Blas, ResourceErrorIdent, Tlas};
20use thiserror::Error;
21use wgt::{AccelerationStructureGeometryFlags, BufferAddress, IndexFormat, VertexFormat};
22
23#[derive(Clone, Debug, Error)]
24pub enum CreateBlasError {
25    #[error(transparent)]
26    Device(#[from] DeviceError),
27    #[error(transparent)]
28    MissingFeatures(#[from] MissingFeatures),
29    #[error(
30        "Only one of 'index_count' and 'index_format' was provided (either provide both or none)"
31    )]
32    MissingIndexData,
33    #[error("Provided format was not within allowed formats. Provided format: {0:?}. Allowed formats: {1:?}")]
34    InvalidVertexFormat(VertexFormat, Vec<VertexFormat>),
35}
36
37#[derive(Clone, Debug, Error)]
38pub enum CreateTlasError {
39    #[error(transparent)]
40    Device(#[from] DeviceError),
41    #[error(transparent)]
42    MissingFeatures(#[from] MissingFeatures),
43}
44
45/// Error encountered while attempting to do a copy on a command encoder.
46#[derive(Clone, Debug, Error)]
47pub enum BuildAccelerationStructureError {
48    #[error(transparent)]
49    Encoder(#[from] CommandEncoderError),
50
51    #[error(transparent)]
52    Device(#[from] DeviceError),
53
54    #[error(transparent)]
55    InvalidResource(#[from] InvalidResourceError),
56
57    #[error(transparent)]
58    DestroyedResource(#[from] DestroyedResourceError),
59
60    #[error(transparent)]
61    MissingBufferUsage(#[from] MissingBufferUsageError),
62
63    #[error(transparent)]
64    MissingFeatures(#[from] MissingFeatures),
65
66    #[error(
67        "Buffer {0:?} size is insufficient for provided size information (size: {1}, required: {2}"
68    )]
69    InsufficientBufferSize(ResourceErrorIdent, u64, u64),
70
71    #[error("Buffer {0:?} associated offset doesn't align with the index type")]
72    UnalignedIndexBufferOffset(ResourceErrorIdent),
73
74    #[error("Buffer {0:?} associated offset is unaligned")]
75    UnalignedTransformBufferOffset(ResourceErrorIdent),
76
77    #[error("Buffer {0:?} associated index count not divisible by 3 (count: {1}")]
78    InvalidIndexCount(ResourceErrorIdent, u32),
79
80    #[error("Buffer {0:?} associated data contains None")]
81    MissingAssociatedData(ResourceErrorIdent),
82
83    #[error(
84        "Blas {0:?} build sizes to may be greater than the descriptor at build time specified"
85    )]
86    IncompatibleBlasBuildSizes(ResourceErrorIdent),
87
88    #[error("Blas {0:?} flags are different, creation flags: {1:?}, provided: {2:?}")]
89    IncompatibleBlasFlags(
90        ResourceErrorIdent,
91        AccelerationStructureGeometryFlags,
92        AccelerationStructureGeometryFlags,
93    ),
94
95    #[error("Blas {0:?} build vertex count is greater than creation count (needs to be less than or equal to), creation: {1:?}, build: {2:?}")]
96    IncompatibleBlasVertexCount(ResourceErrorIdent, u32, u32),
97
98    #[error("Blas {0:?} vertex formats are different, creation format: {1:?}, provided: {2:?}")]
99    DifferentBlasVertexFormats(ResourceErrorIdent, VertexFormat, VertexFormat),
100
101    #[error("Blas {0:?} index count was provided at creation or building, but not the other")]
102    BlasIndexCountProvidedMismatch(ResourceErrorIdent),
103
104    #[error("Blas {0:?} build index count is greater than creation count (needs to be less than or equal to), creation: {1:?}, build: {2:?}")]
105    IncompatibleBlasIndexCount(ResourceErrorIdent, u32, u32),
106
107    #[error("Blas {0:?} index formats are different, creation format: {1:?}, provided: {2:?}")]
108    DifferentBlasIndexFormats(ResourceErrorIdent, Option<IndexFormat>, Option<IndexFormat>),
109
110    #[error("Blas {0:?} build sizes require index buffer but none was provided")]
111    MissingIndexBuffer(ResourceErrorIdent),
112
113    #[error(
114        "Tlas {0:?} an associated instances contains an invalid custom index (more than 24bits)"
115    )]
116    TlasInvalidCustomIndex(ResourceErrorIdent),
117
118    #[error(
119        "Tlas {0:?} has {1} active instances but only {2} are allowed as specified by the descriptor at creation"
120    )]
121    TlasInstanceCountExceeded(ResourceErrorIdent, u32, u32),
122}
123
124#[derive(Clone, Debug, Error)]
125pub enum ValidateBlasActionsError {
126    #[error("Blas {0:?} is used before it is built")]
127    UsedUnbuilt(ResourceErrorIdent),
128}
129
130#[derive(Clone, Debug, Error)]
131pub enum ValidateTlasActionsError {
132    #[error(transparent)]
133    DestroyedResource(#[from] DestroyedResourceError),
134
135    #[error("Tlas {0:?} is used before it is built")]
136    UsedUnbuilt(ResourceErrorIdent),
137
138    #[error("Blas {0:?} is used before it is built (in Tlas {1:?})")]
139    UsedUnbuiltBlas(ResourceErrorIdent, ResourceErrorIdent),
140
141    #[error("Blas {0:?} is newer than the containing Tlas {1:?}")]
142    BlasNewerThenTlas(ResourceErrorIdent, ResourceErrorIdent),
143}
144
145#[derive(Debug)]
146pub struct BlasTriangleGeometry<'a> {
147    pub size: &'a wgt::BlasTriangleGeometrySizeDescriptor,
148    pub vertex_buffer: BufferId,
149    pub index_buffer: Option<BufferId>,
150    pub transform_buffer: Option<BufferId>,
151    pub first_vertex: u32,
152    pub vertex_stride: BufferAddress,
153    pub first_index: Option<u32>,
154    pub transform_buffer_offset: Option<BufferAddress>,
155}
156
157pub enum BlasGeometries<'a> {
158    TriangleGeometries(Box<dyn Iterator<Item = BlasTriangleGeometry<'a>> + 'a>),
159}
160
161pub struct BlasBuildEntry<'a> {
162    pub blas_id: BlasId,
163    pub geometries: BlasGeometries<'a>,
164}
165
166#[derive(Debug, Clone)]
167#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
168pub struct TlasBuildEntry {
169    pub tlas_id: TlasId,
170    pub instance_buffer_id: BufferId,
171    pub instance_count: u32,
172}
173
174#[derive(Debug)]
175pub struct TlasInstance<'a> {
176    pub blas_id: BlasId,
177    pub transform: &'a [f32; 12],
178    pub custom_index: u32,
179    pub mask: u8,
180}
181
182pub struct TlasPackage<'a> {
183    pub tlas_id: TlasId,
184    pub instances: Box<dyn Iterator<Item = Option<TlasInstance<'a>>> + 'a>,
185    pub lowest_unmodified: u32,
186}
187
188#[derive(Debug, Copy, Clone)]
189pub(crate) enum BlasActionKind {
190    Build(NonZeroU64),
191    Use,
192}
193
194#[derive(Debug, Clone)]
195pub(crate) enum TlasActionKind {
196    Build {
197        build_index: NonZeroU64,
198        dependencies: Vec<Arc<Blas>>,
199    },
200    Use,
201}
202
203#[derive(Debug, Clone)]
204pub(crate) struct BlasAction {
205    pub blas: Arc<Blas>,
206    pub kind: BlasActionKind,
207}
208
209#[derive(Debug, Clone)]
210pub(crate) struct TlasAction {
211    pub tlas: Arc<Tlas>,
212    pub kind: TlasActionKind,
213}
214
215#[derive(Debug, Clone)]
216#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
217pub struct TraceBlasTriangleGeometry {
218    pub size: wgt::BlasTriangleGeometrySizeDescriptor,
219    pub vertex_buffer: BufferId,
220    pub index_buffer: Option<BufferId>,
221    pub transform_buffer: Option<BufferId>,
222    pub first_vertex: u32,
223    pub vertex_stride: BufferAddress,
224    pub first_index: Option<u32>,
225    pub transform_buffer_offset: Option<BufferAddress>,
226}
227
228#[derive(Debug, Clone)]
229#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
230pub enum TraceBlasGeometries {
231    TriangleGeometries(Vec<TraceBlasTriangleGeometry>),
232}
233
234#[derive(Debug, Clone)]
235#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
236pub struct TraceBlasBuildEntry {
237    pub blas_id: BlasId,
238    pub geometries: TraceBlasGeometries,
239}
240
241#[derive(Debug, Clone)]
242#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
243pub struct TraceTlasInstance {
244    pub blas_id: BlasId,
245    pub transform: [f32; 12],
246    pub custom_index: u32,
247    pub mask: u8,
248}
249
250#[derive(Debug, Clone)]
251#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
252pub struct TraceTlasPackage {
253    pub tlas_id: TlasId,
254    pub instances: Vec<Option<TraceTlasInstance>>,
255    pub lowest_unmodified: u32,
256}