Skip to main content

vk_graph/cmd/
cmd_ref.rs

1use {
2    crate::{
3        AnyAccelerationStructureNode, AnyResource, Node,
4        driver::{
5            accel_struct::{
6                AccelerationStructureGeometry, AccelerationStructureGeometryInfo,
7                DeviceOrHostAddress,
8            },
9            device::Device,
10        },
11    },
12    ash::vk,
13    log::trace,
14    std::{cell::RefCell, ops::Deref},
15};
16
17#[cfg(debug_assertions)]
18use crate::Execution;
19
20/// Recording interface for general Vulkan commands.
21///
22/// This structure provides a strongly-typed set of methods which allow acceleration structures to
23/// be built and updated.
24///
25/// # Examples
26///
27/// Basic usage:
28///
29/// ```no_run
30/// # use ash::vk;
31/// # use vk_graph::Graph;
32/// # fn main() {
33/// # let mut my_graph = Graph::default();
34/// my_graph.begin_cmd()
35///         .record_cmd(move |cmd| {
36///             // Use provided command buffer functions or native calls
37///             assert_ne!(cmd.handle, vk::CommandBuffer::null());
38///         });
39/// # }
40/// ```
41#[derive(Clone, Copy)]
42pub struct CommandRef<'a> {
43    cmd: &'a crate::driver::cmd_buf::CommandBuffer,
44
45    #[cfg(debug_assertions)]
46    exec: &'a Execution,
47
48    resources: &'a [AnyResource],
49}
50
51impl<'a> CommandRef<'a> {
52    pub(crate) fn new(
53        cmd: &'a crate::driver::cmd_buf::CommandBuffer,
54        resources: &'a [AnyResource],
55        #[cfg(debug_assertions)] exec: &'a Execution,
56    ) -> Self {
57        Self {
58            cmd,
59            #[cfg(debug_assertions)]
60            exec,
61            resources,
62        }
63    }
64
65    /// Build acceleration structures.
66    ///
67    /// There is no ordering or synchronization implied between any of the individual acceleration
68    /// structure builds.
69    ///
70    /// Requires a scratch buffer which was created with the following requirements:
71    ///
72    /// - Flags must include [`vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS`]
73    /// - Size must be equal to or greater than the `build_size` value returned by
74    ///   `AccelerationStructure::size_of`, aligned to `min_accel_struct_scratch_offset_alignment`
75    ///   of `PhysicalDevice::accel_struct_properties`.
76    ///
77    /// # Examples
78    ///
79    /// Basic usage:
80    ///
81    /// ```no_run
82    /// # use ash::vk;
83    /// # use vk_graph::cmd::BuildAccelerationStructureInfo;
84    /// # use vk_graph::driver::{sync::AccessType, DriverError};
85    /// # use vk_graph::driver::device::{Device, DeviceInfo};
86    /// # use vk_graph::driver::accel_struct::{
87    /// #     AccelerationStructure,
88    /// #     AccelerationStructureGeometry,
89    /// #     AccelerationStructureGeometryData,
90    /// #     AccelerationStructureGeometryInfo,
91    /// #     AccelerationStructureInfo,
92    /// #     DeviceOrHostAddress,
93    /// # };
94    /// # use vk_graph::driver::buffer::{Buffer, BufferInfo};
95    /// # use vk_graph::Graph;
96    /// # use vk_graph::driver::shader::Shader;
97    /// # fn main() -> Result<(), DriverError> {
98    /// # let device = Device::new(DeviceInfo::default())?;
99    /// # let mut my_graph = Graph::default();
100    /// # let info = AccelerationStructureInfo::blas(1);
101    /// # let blas_accel_struct = AccelerationStructure::create(&device, info)?;
102    /// # let blas_node = my_graph.bind_resource(blas_accel_struct);
103    /// # let scratch_buf_info =
104    /// #     BufferInfo::device_mem(8, vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS);
105    /// # let scratch_buf = Buffer::create(&device, scratch_buf_info)?;
106    /// # let scratch_buf = my_graph.bind_resource(scratch_buf);
107    /// # let buf_info = BufferInfo::device_mem(8, vk::BufferUsageFlags::INDEX_BUFFER);
108    /// # let my_idx_buf = Buffer::create(&device, buf_info)?;
109    /// # let buf_info = BufferInfo::device_mem(8, vk::BufferUsageFlags::VERTEX_BUFFER);
110    /// # let my_vtx_buf = Buffer::create(&device, buf_info)?;
111    /// # let index_buf = my_graph.bind_resource(my_idx_buf);
112    /// # let vertex_buf = my_graph.bind_resource(my_vtx_buf);
113    /// my_graph.begin_cmd()
114    ///         .resource_access(index_buf, AccessType::IndexBuffer)
115    ///         .resource_access(vertex_buf, AccessType::VertexBuffer)
116    ///         .resource_access(scratch_buf, AccessType::AccelerationStructureBufferWrite)
117    ///         .resource_access(blas_node, AccessType::AccelerationStructureBuildWrite)
118    ///         .record_cmd(move |cmd| {
119    ///             let scratch_addr = cmd.resource(scratch_buf).device_address();
120    ///             let geom = AccelerationStructureGeometry {
121    ///                 max_primitive_count: 64,
122    ///                 flags: vk::GeometryFlagsKHR::OPAQUE,
123    ///                 geometry: AccelerationStructureGeometryData::Triangles {
124    ///                     index_addr: DeviceOrHostAddress::DeviceAddress(
125    ///                         cmd.resource(index_buf).device_address()
126    ///                     ),
127    ///                     index_type: vk::IndexType::UINT32,
128    ///                     max_vertex: 42,
129    ///                     transform_addr: None,
130    ///                     vertex_addr: DeviceOrHostAddress::DeviceAddress(
131    ///                         cmd.resource(vertex_buf).device_address(),
132    ///                     ),
133    ///                     vertex_format: vk::Format::R32G32B32_SFLOAT,
134    ///                     vertex_stride: 12,
135    ///                 },
136    ///             };
137    ///             let build_range = vk::AccelerationStructureBuildRangeInfoKHR {
138    ///                 first_vertex: 0,
139    ///                 primitive_count: 1,
140    ///                 primitive_offset: 0,
141    ///                 transform_offset: 0,
142    ///             };
143    ///             let info = AccelerationStructureGeometryInfo::blas([(geom, build_range)]);
144    ///
145    ///             cmd.build_accel_struct(&[
146    ///                 BuildAccelerationStructureInfo::new(blas_node, scratch_addr, info)
147    ///             ]);
148    ///         });
149    /// # Ok(()) }
150    /// ```
151    ///
152    /// See also:
153    ///
154    /// - [`examples/ray_omni.rs`](/examples/ray_omni.rs)
155    /// - [`examples/ray_trace.rs`](/examples/ray_trace.rs)
156    /// - [`examples/rt_triangle.rs`](/examples/rt_triangle.rs)
157    pub fn build_accel_struct(&self, infos: &[BuildAccelerationStructureInfo]) -> &Self {
158        #[derive(Default)]
159        struct Tls {
160            geometries: Vec<vk::AccelerationStructureGeometryKHR<'static>>,
161            ranges: Vec<vk::AccelerationStructureBuildRangeInfoKHR>,
162        }
163
164        thread_local! {
165            static TLS: RefCell<Tls> = Default::default();
166        }
167
168        TLS.with_borrow_mut(|tls| {
169            tls.geometries.clear();
170            tls.geometries.extend(infos.iter().flat_map(|info| {
171                info.build_data.geometries.iter().map(|(geometry, _)| {
172                    <&AccelerationStructureGeometry as Into<
173                            vk::AccelerationStructureGeometryKHR,
174                        >>::into(geometry)
175                })
176            }));
177
178            tls.ranges.clear();
179            tls.ranges.extend(
180                infos
181                    .iter()
182                    .flat_map(|info| info.build_data.geometries.iter().map(|(_, range)| *range)),
183            );
184
185            let vk_ranges = {
186                let mut start = 0;
187                let mut vk_ranges = Vec::with_capacity(infos.len());
188                for info in infos {
189                    let end = start + info.build_data.geometries.len();
190                    vk_ranges.push(&tls.ranges[start..end]);
191                    start = end;
192                }
193
194                vk_ranges
195            };
196
197            let vk_infos = {
198                let mut start = 0;
199                let mut vk_infos = Vec::with_capacity(infos.len());
200                for info in infos {
201                    let end = start + info.build_data.geometries.len();
202                    vk_infos.push(
203                        vk::AccelerationStructureBuildGeometryInfoKHR::default()
204                            .ty(info.build_data.ty)
205                            .flags(info.build_data.flags)
206                            .mode(vk::BuildAccelerationStructureModeKHR::BUILD)
207                            .dst_acceleration_structure(self.resource(info.accel_struct).handle)
208                            .geometries(&tls.geometries[start..end])
209                            .scratch_data(info.scratch_addr.into()),
210                    );
211                    start = end;
212                }
213
214                vk_infos
215            };
216
217            unsafe {
218                Device::expect_accel_struct_ext(&self.cmd.device)
219                    .cmd_build_acceleration_structures(self.cmd.handle, &vk_infos, &vk_ranges);
220            }
221        });
222
223        self
224    }
225
226    /// Builds acceleration structures with some parameters provided on the device.
227    ///
228    /// There is no ordering or synchronization implied between any of the individual acceleration
229    /// structure builds.
230    ///
231    /// Each [`BuildAccelerationStructureIndirectInfo::range_base`] is a buffer device address which
232    /// points to an array of [`vk::AccelerationStructureBuildRangeInfoKHR`] structures defining
233    /// dynamic offsets to the addresses where geometry data is stored.
234    pub fn build_accel_struct_indirect(
235        &self,
236        infos: &[BuildAccelerationStructureIndirectInfo],
237    ) -> &Self {
238        #[derive(Default)]
239        struct Tls {
240            geometries: Vec<vk::AccelerationStructureGeometryKHR<'static>>,
241            max_primitive_counts: Vec<u32>,
242            range_bases: Vec<vk::DeviceAddress>,
243            range_strides: Vec<u32>,
244        }
245
246        thread_local! {
247            static TLS: RefCell<Tls> = Default::default();
248        }
249
250        TLS.with_borrow_mut(|tls| {
251            tls.geometries.clear();
252            tls.geometries.extend(infos.iter().flat_map(|info| {
253                info.build_data.geometries.iter().map(
254                    <&AccelerationStructureGeometry as Into<
255                        vk::AccelerationStructureGeometryKHR,
256                    >>::into,
257                )
258            }));
259
260            tls.max_primitive_counts.clear();
261            tls.max_primitive_counts
262                .extend(infos.iter().flat_map(|info| {
263                    info.build_data
264                        .geometries
265                        .iter()
266                        .map(|geometry| geometry.max_primitive_count)
267                }));
268
269            tls.range_bases.clear();
270            tls.range_strides.clear();
271            let (vk_infos, vk_max_primitive_counts) = {
272                let mut start = 0;
273                let mut vk_infos = Vec::with_capacity(infos.len());
274                let mut vk_max_primitive_counts = Vec::with_capacity(infos.len());
275                for info in infos {
276                    let end = start + info.build_data.geometries.len();
277                    vk_infos.push(
278                        vk::AccelerationStructureBuildGeometryInfoKHR::default()
279                            .ty(info.build_data.ty)
280                            .flags(info.build_data.flags)
281                            .mode(vk::BuildAccelerationStructureModeKHR::BUILD)
282                            .dst_acceleration_structure(self.resource(info.accel_struct).handle)
283                            .geometries(&tls.geometries[start..end])
284                            .scratch_data(info.scratch_data.into()),
285                    );
286                    vk_max_primitive_counts.push(&tls.max_primitive_counts[start..end]);
287                    start = end;
288
289                    tls.range_bases.push(info.range_base);
290                    tls.range_strides.push(info.range_stride);
291                }
292
293                (vk_infos, vk_max_primitive_counts)
294            };
295
296            unsafe {
297                Device::expect_accel_struct_ext(&self.cmd.device)
298                    .cmd_build_acceleration_structures_indirect(
299                        self.cmd.handle,
300                        &vk_infos,
301                        &tls.range_bases,
302                        &tls.range_strides,
303                        &vk_max_primitive_counts,
304                    );
305            }
306        });
307
308        self
309    }
310
311    pub(crate) fn cmd_push_constants(
312        &self,
313        layout: vk::PipelineLayout,
314        push_consts: &[vk::PushConstantRange],
315        offset: u32,
316        data: &[u8],
317    ) {
318        for push_const in push_consts {
319            let push_const_end = push_const.offset + push_const.size;
320            let data_end = offset + data.len() as u32;
321            let end = data_end.min(push_const_end);
322            let start = offset.max(push_const.offset);
323
324            if end > start {
325                trace!(
326                    "      push constants {:?} {}..{}",
327                    push_const.stage_flags, start, end
328                );
329
330                unsafe {
331                    self.device.cmd_push_constants(
332                        self.handle,
333                        layout,
334                        push_const.stage_flags,
335                        start,
336                        &data[(start - offset) as usize..(end - offset) as usize],
337                    );
338                }
339            }
340        }
341    }
342
343    /// Update acceleration structures.
344    ///
345    /// There is no ordering or synchronization implied between any of the individual acceleration
346    /// structure updates.
347    ///
348    /// Requires a scratch buffer which was created with the following requirements:
349    ///
350    /// - Flags must include [`vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS`]
351    /// - Size must be equal to or greater than the `update_size` value returned by
352    ///   `AccelerationStructure::size_of`, aligned to `min_accel_struct_scratch_offset_alignment`
353    ///   of `PhysicalDevice::accel_struct_properties`.
354    pub fn update_accel_struct(&self, infos: &[UpdateAccelerationStructureInfo]) -> &Self {
355        #[derive(Default)]
356        struct Tls {
357            geometries: Vec<vk::AccelerationStructureGeometryKHR<'static>>,
358            ranges: Vec<vk::AccelerationStructureBuildRangeInfoKHR>,
359        }
360
361        thread_local! {
362            static TLS: RefCell<Tls> = Default::default();
363        }
364
365        TLS.with_borrow_mut(|tls| {
366            tls.geometries.clear();
367            tls.geometries.extend(infos.iter().flat_map(|info| {
368                info.update_data.geometries.iter().map(|(geometry, _)| {
369                    <&AccelerationStructureGeometry as Into<
370                            vk::AccelerationStructureGeometryKHR,
371                        >>::into(geometry)
372                })
373            }));
374
375            tls.ranges.clear();
376            tls.ranges.extend(
377                infos
378                    .iter()
379                    .flat_map(|info| info.update_data.geometries.iter().map(|(_, range)| *range)),
380            );
381
382            let vk_ranges = {
383                let mut start = 0;
384                let mut vk_ranges = Vec::with_capacity(infos.len());
385                for info in infos {
386                    let end = start + info.update_data.geometries.len();
387                    vk_ranges.push(&tls.ranges[start..end]);
388                    start = end;
389                }
390
391                vk_ranges
392            };
393
394            let vk_infos = {
395                let mut start = 0;
396                let mut vk_infos = Vec::with_capacity(infos.len());
397                for info in infos {
398                    let end = start + info.update_data.geometries.len();
399                    vk_infos.push(
400                        vk::AccelerationStructureBuildGeometryInfoKHR::default()
401                            .ty(info.update_data.ty)
402                            .flags(info.update_data.flags)
403                            .mode(vk::BuildAccelerationStructureModeKHR::UPDATE)
404                            .dst_acceleration_structure(self.resource(info.dst_accel_struct).handle)
405                            .src_acceleration_structure(self.resource(info.src_accel_struct).handle)
406                            .geometries(&tls.geometries[start..end])
407                            .scratch_data(info.scratch_addr.into()),
408                    );
409                    start = end;
410                }
411
412                vk_infos
413            };
414
415            unsafe {
416                Device::expect_accel_struct_ext(&self.cmd.device)
417                    .cmd_build_acceleration_structures(self.cmd.handle, &vk_infos, &vk_ranges);
418            }
419        });
420
421        self
422    }
423
424    /// Updates acceleration structures with some parameters provided on the device.
425    ///
426    /// There is no ordering or synchronization implied between any of the individual acceleration
427    /// structure updates.
428    ///
429    /// Each [`UpdateAccelerationStructureIndirectInfo::range_base`] is a buffer device address
430    /// which points to an array of [`vk::AccelerationStructureBuildRangeInfoKHR`] structures
431    /// defining dynamic offsets to the addresses where geometry data is stored.
432    pub fn update_accel_struct_indirect(
433        &self,
434        infos: &[UpdateAccelerationStructureIndirectInfo],
435    ) -> &Self {
436        #[derive(Default)]
437        struct Tls {
438            geometries: Vec<vk::AccelerationStructureGeometryKHR<'static>>,
439            max_primitive_counts: Vec<u32>,
440            range_bases: Vec<vk::DeviceAddress>,
441            range_strides: Vec<u32>,
442        }
443
444        thread_local! {
445            static TLS: RefCell<Tls> = Default::default();
446        }
447
448        TLS.with_borrow_mut(|tls| {
449            tls.geometries.clear();
450            tls.geometries.extend(infos.iter().flat_map(|info| {
451                info.update_data.geometries.iter().map(
452                    <&AccelerationStructureGeometry as Into<
453                        vk::AccelerationStructureGeometryKHR,
454                    >>::into,
455                )
456            }));
457
458            tls.max_primitive_counts.clear();
459            tls.max_primitive_counts
460                .extend(infos.iter().flat_map(|info| {
461                    info.update_data
462                        .geometries
463                        .iter()
464                        .map(|geometry| geometry.max_primitive_count)
465                }));
466
467            tls.range_bases.clear();
468            tls.range_strides.clear();
469            let (vk_infos, vk_max_primitive_counts) = {
470                let mut start = 0;
471                let mut vk_infos = Vec::with_capacity(infos.len());
472                let mut vk_max_primitive_counts = Vec::with_capacity(infos.len());
473                for info in infos {
474                    let end = start + info.update_data.geometries.len();
475                    vk_infos.push(
476                        vk::AccelerationStructureBuildGeometryInfoKHR::default()
477                            .ty(info.update_data.ty)
478                            .flags(info.update_data.flags)
479                            .mode(vk::BuildAccelerationStructureModeKHR::UPDATE)
480                            .src_acceleration_structure(self.resource(info.src_accel_struct).handle)
481                            .dst_acceleration_structure(self.resource(info.dst_accel_struct).handle)
482                            .geometries(&tls.geometries[start..end])
483                            .scratch_data(info.scratch_addr.into()),
484                    );
485                    vk_max_primitive_counts.push(&tls.max_primitive_counts[start..end]);
486                    start = end;
487
488                    tls.range_bases.push(info.range_base);
489                    tls.range_strides.push(info.range_stride);
490                }
491
492                (vk_infos, vk_max_primitive_counts)
493            };
494
495            unsafe {
496                Device::expect_accel_struct_ext(&self.cmd.device)
497                    .cmd_build_acceleration_structures_indirect(
498                        self.cmd.handle,
499                        &vk_infos,
500                        &tls.range_bases,
501                        &tls.range_strides,
502                        &vk_max_primitive_counts,
503                    );
504            }
505        });
506
507        self
508    }
509
510    /// Returns a borrow of the original Vulkan resource (buffer, image or acceleration structure)
511    /// which the given bound resource node represents.
512    pub fn resource<N>(&self, resource_node: N) -> &N::Resource
513    where
514        N: Node,
515    {
516        // You must have called an access function for this node on this execution before borrowing
517        // the resource!
518        //
519        // Why: Code that attempts to access this function is attempting to get access to the Vulkan
520        // resource (buffer, image, or acceleration structure). In order to access any resources the
521        // access type must first be specified so the correct barriers may be added.
522        //
523        // See: https://attackgoat.github.io/vk-graph/pipeline_sync.html
524        #[cfg(debug_assertions)]
525        assert!(
526            self.exec.accesses.contains_key(&resource_node.index()),
527            "unexpected node access: call an access function first"
528        );
529
530        resource_node.borrow(self.resources)
531    }
532}
533
534impl<'a> Deref for CommandRef<'a> {
535    type Target = crate::driver::cmd_buf::CommandBuffer;
536
537    fn deref(&self) -> &Self::Target {
538        self.cmd
539    }
540}
541
542/// Specifies the information and data used to build an acceleration structure.
543///
544/// See [`vkCmdBuildAccelerationStructuresKHR`](https://registry.khronos.org/vulkan/specs/latest/man/html/vkCmdBuildAccelerationStructuresKHR.html).
545#[derive(Clone, Debug)]
546pub struct BuildAccelerationStructureInfo {
547    /// The acceleration structure to be written.
548    pub accel_struct: AnyAccelerationStructureNode,
549
550    /// Specifies the geometry data to use when building the acceleration structure.
551    pub build_data: AccelerationStructureGeometryInfo<(
552        AccelerationStructureGeometry,
553        vk::AccelerationStructureBuildRangeInfoKHR,
554    )>,
555
556    /// The temporary buffer or host address (with enough capacity per
557    /// `AccelerationStructure::size_of`).
558    pub scratch_addr: DeviceOrHostAddress,
559}
560
561impl BuildAccelerationStructureInfo {
562    /// Constructs new acceleration structure build information.
563    pub fn new(
564        accel_struct: impl Into<AnyAccelerationStructureNode>,
565        scratch_addr: impl Into<DeviceOrHostAddress>,
566        build_data: AccelerationStructureGeometryInfo<(
567            AccelerationStructureGeometry,
568            vk::AccelerationStructureBuildRangeInfoKHR,
569        )>,
570    ) -> Self {
571        let accel_struct = accel_struct.into();
572        let scratch_addr = scratch_addr.into();
573
574        Self {
575            accel_struct,
576            build_data,
577            scratch_addr,
578        }
579    }
580}
581
582/// Specifies the information and data used to build an acceleration structure with some parameters
583/// sourced on the device.
584///
585/// See [`vkCmdBuildAccelerationStructuresKHR`](https://registry.khronos.org/vulkan/specs/latest/man/html/vkCmdBuildAccelerationStructuresKHR.html).
586#[derive(Clone, Debug)]
587pub struct BuildAccelerationStructureIndirectInfo {
588    /// The acceleration structure to be written.
589    pub accel_struct: AnyAccelerationStructureNode,
590
591    /// Specifies the geometry data to use when building the acceleration structure.
592    pub build_data: AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
593
594    /// A buffer device addresses which points to `data.geometry.len()`
595    /// [vk::AccelerationStructureBuildRangeInfoKHR] structures defining dynamic offsets to the
596    /// addresses where geometry data is stored.
597    pub range_base: vk::DeviceAddress,
598
599    /// Byte stride between elements of [`Self::range_base`].
600    pub range_stride: u32,
601
602    /// The temporary buffer or host address (with enough capacity per
603    /// `AccelerationStructure::size_of`).
604    pub scratch_data: DeviceOrHostAddress,
605}
606
607impl BuildAccelerationStructureIndirectInfo {
608    /// Constructs new acceleration structure indirect build information.
609    pub fn new(
610        accel_struct: impl Into<AnyAccelerationStructureNode>,
611        scratch_data: impl Into<DeviceOrHostAddress>,
612        build_data: AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
613        range_base: vk::DeviceAddress,
614        range_stride: u32,
615    ) -> Self {
616        let accel_struct = accel_struct.into();
617        let scratch_data = scratch_data.into();
618
619        Self {
620            accel_struct,
621            build_data,
622            range_base,
623            range_stride,
624            scratch_data,
625        }
626    }
627}
628
629/// Specifies the information and data used to update an acceleration structure with some parameters
630/// sourced on the device.
631///
632/// See [`vkCmdBuildAccelerationStructuresKHR`](https://registry.khronos.org/vulkan/specs/latest/man/html/vkCmdBuildAccelerationStructuresKHR.html).
633#[derive(Clone, Debug)]
634pub struct UpdateAccelerationStructureIndirectInfo {
635    /// The acceleration structure to be written.
636    pub dst_accel_struct: AnyAccelerationStructureNode,
637
638    /// A buffer device addresses which points to `data.geometry.len()`
639    /// [vk::AccelerationStructureBuildRangeInfoKHR] structures defining dynamic offsets to the
640    /// addresses where geometry data is stored.
641    pub range_base: vk::DeviceAddress,
642
643    /// Byte stride between elements of [`Self::range_base`].
644    pub range_stride: u32,
645
646    /// The temporary buffer or host address (with enough capacity per
647    /// `AccelerationStructure::size_of`).
648    pub scratch_addr: DeviceOrHostAddress,
649
650    /// The source acceleration structure to be read.
651    pub src_accel_struct: AnyAccelerationStructureNode,
652
653    /// Specifies the geometry data to use when building the acceleration structure.
654    pub update_data: AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
655}
656
657impl UpdateAccelerationStructureIndirectInfo {
658    /// Constructs new acceleration structure indirect update information.
659    pub fn new(
660        src_accel_struct: impl Into<AnyAccelerationStructureNode>,
661        dst_accel_struct: impl Into<AnyAccelerationStructureNode>,
662        scratch_addr: impl Into<DeviceOrHostAddress>,
663        update_data: AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
664        range_base: vk::DeviceAddress,
665        range_stride: u32,
666    ) -> Self {
667        let src_accel_struct = src_accel_struct.into();
668        let dst_accel_struct = dst_accel_struct.into();
669        let scratch_addr = scratch_addr.into();
670
671        Self {
672            dst_accel_struct,
673            range_base,
674            range_stride,
675            scratch_addr,
676            src_accel_struct,
677            update_data,
678        }
679    }
680}
681
682/// Specifies the information and data used to update an acceleration structure.
683#[derive(Clone, Debug)]
684pub struct UpdateAccelerationStructureInfo {
685    /// The acceleration structure to be written.
686    pub dst_accel_struct: AnyAccelerationStructureNode,
687
688    /// The temporary buffer or host address (with enough capacity per
689    /// `AccelerationStructure::size_of`).
690    pub scratch_addr: DeviceOrHostAddress,
691
692    /// The source acceleration structure to be read.
693    pub src_accel_struct: AnyAccelerationStructureNode,
694
695    /// Specifies the geometry data to use when updating the acceleration structure.
696    pub update_data: AccelerationStructureGeometryInfo<(
697        AccelerationStructureGeometry,
698        vk::AccelerationStructureBuildRangeInfoKHR,
699    )>,
700}
701
702impl UpdateAccelerationStructureInfo {
703    /// Constructs new acceleration structure update information.
704    pub fn new(
705        src_accel_struct: impl Into<AnyAccelerationStructureNode>,
706        dst_accel_struct: impl Into<AnyAccelerationStructureNode>,
707        scratch_addr: impl Into<DeviceOrHostAddress>,
708        update_data: AccelerationStructureGeometryInfo<(
709            AccelerationStructureGeometry,
710            vk::AccelerationStructureBuildRangeInfoKHR,
711        )>,
712    ) -> Self {
713        let src_accel_struct = src_accel_struct.into();
714        let dst_accel_struct = dst_accel_struct.into();
715        let scratch_addr = scratch_addr.into();
716
717        Self {
718            dst_accel_struct,
719            scratch_addr,
720            src_accel_struct,
721            update_data,
722        }
723    }
724}
725
726#[allow(missing_docs)]
727#[allow(deprecated)]
728mod deprecated {
729    use ash::vk;
730
731    use crate::{
732        cmd::{
733            BuildAccelerationStructureIndirectInfo, BuildAccelerationStructureInfo, CommandRef,
734            UpdateAccelerationStructureIndirectInfo, UpdateAccelerationStructureInfo,
735        },
736        driver::accel_struct::{
737            AccelerationStructureGeometry, AccelerationStructureGeometryInfo, DeviceOrHostAddress,
738        },
739        graph::pass_ref::{
740            AccelerationStructureBuildInfo, AccelerationStructureIndirectBuildInfo,
741            AccelerationStructureIndirectUpdateInfo, AccelerationStructureUpdateInfo,
742        },
743        node::AnyAccelerationStructureNode,
744    };
745
746    impl<'a> CommandRef<'a> {
747        #[deprecated = "use build_accel_struct function"]
748        #[doc(hidden)]
749        pub fn build_structure(
750            &self,
751            info: &AccelerationStructureGeometryInfo<(
752                AccelerationStructureGeometry,
753                vk::AccelerationStructureBuildRangeInfoKHR,
754            )>,
755            accel_struct: impl Into<AnyAccelerationStructureNode>,
756            scratch_addr: impl Into<DeviceOrHostAddress>,
757        ) -> &Self {
758            self.build_accel_struct(&[BuildAccelerationStructureInfo {
759                accel_struct: accel_struct.into(),
760                build_data: info.clone(),
761                scratch_addr: scratch_addr.into(),
762            }])
763        }
764
765        #[deprecated = "use build_accel_struct_indirect function"]
766        #[doc(hidden)]
767        pub fn build_structure_indirect(
768            &self,
769            info: &AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
770            accel_struct: impl Into<AnyAccelerationStructureNode>,
771            scratch_addr: impl Into<DeviceOrHostAddress>,
772            range_base: vk::DeviceAddress,
773            range_stride: u32,
774        ) -> &Self {
775            self.build_accel_struct_indirect(&[BuildAccelerationStructureIndirectInfo {
776                accel_struct: accel_struct.into(),
777                build_data: info.clone(),
778                range_base,
779                range_stride,
780                scratch_data: scratch_addr.into(),
781            }])
782        }
783
784        #[deprecated = "use build_accel_struct function"]
785        #[doc(hidden)]
786        pub fn build_structures(&self, infos: &[AccelerationStructureBuildInfo]) -> &Self {
787            for info in infos {
788                self.build_structure(&info.build_data, info.accel_struct, info.scratch_addr);
789            }
790
791            self
792        }
793
794        #[deprecated = "use build_accel_struct_indirect function"]
795        #[doc(hidden)]
796        pub fn build_structures_indirect(
797            &self,
798            infos: &[AccelerationStructureIndirectBuildInfo],
799        ) -> &Self {
800            for info in infos {
801                self.build_structure_indirect(
802                    &info.build_data,
803                    info.accel_struct,
804                    info.scratch_data,
805                    info.range_base,
806                    info.range_stride,
807                );
808            }
809
810            self
811        }
812
813        #[deprecated = "use update_accel_struct function"]
814        #[doc(hidden)]
815        pub fn update_structure(
816            &self,
817            info: &AccelerationStructureGeometryInfo<(
818                AccelerationStructureGeometry,
819                vk::AccelerationStructureBuildRangeInfoKHR,
820            )>,
821            src_accel_struct: impl Into<AnyAccelerationStructureNode>,
822            dst_accel_struct: impl Into<AnyAccelerationStructureNode>,
823            scratch_addr: impl Into<DeviceOrHostAddress>,
824        ) -> &Self {
825            self.update_accel_struct(&[UpdateAccelerationStructureInfo {
826                src_accel_struct: src_accel_struct.into(),
827                dst_accel_struct: dst_accel_struct.into(),
828                update_data: info.clone(),
829                scratch_addr: scratch_addr.into(),
830            }])
831        }
832
833        #[deprecated = "use update_accel_struct_indirect function"]
834        #[doc(hidden)]
835        pub fn update_structure_indirect(
836            &self,
837            info: &AccelerationStructureGeometryInfo<AccelerationStructureGeometry>,
838            src_accel_struct: impl Into<AnyAccelerationStructureNode>,
839            dst_accel_struct: impl Into<AnyAccelerationStructureNode>,
840            scratch_addr: impl Into<DeviceOrHostAddress>,
841            range_base: vk::DeviceAddress,
842            range_stride: u32,
843        ) -> &Self {
844            self.update_accel_struct_indirect(&[UpdateAccelerationStructureIndirectInfo {
845                src_accel_struct: src_accel_struct.into(),
846                dst_accel_struct: dst_accel_struct.into(),
847                update_data: info.clone(),
848                range_base,
849                range_stride,
850                scratch_addr: scratch_addr.into(),
851            }])
852        }
853
854        #[deprecated = "use update_accel_struct function"]
855        #[doc(hidden)]
856        pub fn update_structures(&self, infos: &[AccelerationStructureUpdateInfo]) -> &Self {
857            for info in infos {
858                self.update_structure(
859                    &info.update_data,
860                    info.src_accel_struct,
861                    info.dst_accel_struct,
862                    info.scratch_addr,
863                );
864            }
865
866            self
867        }
868
869        #[deprecated = "use update_accel_struct_indirect function"]
870        #[doc(hidden)]
871        pub fn update_structures_indirect(
872            &self,
873            infos: &[AccelerationStructureIndirectUpdateInfo],
874        ) -> &Self {
875            for info in infos {
876                self.update_structure_indirect(
877                    &info.update_data,
878                    info.src_accel_struct,
879                    info.dst_accel_struct,
880                    info.scratch_addr,
881                    info.range_base,
882                    info.range_stride,
883                );
884            }
885
886            self
887        }
888    }
889}