1 use crate::prelude::*;
2 use crate::vk;
3 use crate::RawPtr;
4 use crate::{Device, Instance};
5 use std::ffi::CStr;
6 use std::mem;
7 
8 #[derive(Clone)]
9 pub struct AccelerationStructure {
10     handle: vk::Device,
11     fp: vk::KhrAccelerationStructureFn,
12 }
13 
14 impl AccelerationStructure {
new(instance: &Instance, device: &Device) -> Self15     pub fn new(instance: &Instance, device: &Device) -> Self {
16         let handle = device.handle();
17         let fp = vk::KhrAccelerationStructureFn::load(|name| unsafe {
18             mem::transmute(instance.get_device_proc_addr(handle, name.as_ptr()))
19         });
20         Self { handle, fp }
21     }
22 
23     #[inline]
get_properties( instance: &Instance, pdevice: vk::PhysicalDevice, ) -> vk::PhysicalDeviceAccelerationStructurePropertiesKHR24     pub unsafe fn get_properties(
25         instance: &Instance,
26         pdevice: vk::PhysicalDevice,
27     ) -> vk::PhysicalDeviceAccelerationStructurePropertiesKHR {
28         let mut props_rt = vk::PhysicalDeviceAccelerationStructurePropertiesKHR::default();
29         {
30             let mut props = vk::PhysicalDeviceProperties2::builder().push_next(&mut props_rt);
31             instance.get_physical_device_properties2(pdevice, &mut props);
32         }
33         props_rt
34     }
35 
36     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateAccelerationStructureKHR.html>
37     #[inline]
create_acceleration_structure( &self, create_info: &vk::AccelerationStructureCreateInfoKHR, allocation_callbacks: Option<&vk::AllocationCallbacks>, ) -> VkResult<vk::AccelerationStructureKHR>38     pub unsafe fn create_acceleration_structure(
39         &self,
40         create_info: &vk::AccelerationStructureCreateInfoKHR,
41         allocation_callbacks: Option<&vk::AllocationCallbacks>,
42     ) -> VkResult<vk::AccelerationStructureKHR> {
43         let mut accel_struct = mem::zeroed();
44         (self.fp.create_acceleration_structure_khr)(
45             self.handle,
46             create_info,
47             allocation_callbacks.as_raw_ptr(),
48             &mut accel_struct,
49         )
50         .result_with_success(accel_struct)
51     }
52 
53     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkDestroyAccelerationStructureKHR.html>
54     #[inline]
destroy_acceleration_structure( &self, accel_struct: vk::AccelerationStructureKHR, allocation_callbacks: Option<&vk::AllocationCallbacks>, )55     pub unsafe fn destroy_acceleration_structure(
56         &self,
57         accel_struct: vk::AccelerationStructureKHR,
58         allocation_callbacks: Option<&vk::AllocationCallbacks>,
59     ) {
60         (self.fp.destroy_acceleration_structure_khr)(
61             self.handle,
62             accel_struct,
63             allocation_callbacks.as_raw_ptr(),
64         );
65     }
66 
67     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdBuildAccelerationStructuresKHR.html>
68     #[inline]
cmd_build_acceleration_structures( &self, command_buffer: vk::CommandBuffer, infos: &[vk::AccelerationStructureBuildGeometryInfoKHR], build_range_infos: &[&[vk::AccelerationStructureBuildRangeInfoKHR]], )69     pub unsafe fn cmd_build_acceleration_structures(
70         &self,
71         command_buffer: vk::CommandBuffer,
72         infos: &[vk::AccelerationStructureBuildGeometryInfoKHR],
73         build_range_infos: &[&[vk::AccelerationStructureBuildRangeInfoKHR]],
74     ) {
75         assert_eq!(infos.len(), build_range_infos.len());
76 
77         let build_range_infos = build_range_infos
78             .iter()
79             .zip(infos.iter())
80             .map(|(range_info, info)| {
81                 assert_eq!(range_info.len(), info.geometry_count as usize);
82                 range_info.as_ptr()
83             })
84             .collect::<Vec<_>>();
85 
86         (self.fp.cmd_build_acceleration_structures_khr)(
87             command_buffer,
88             infos.len() as _,
89             infos.as_ptr(),
90             build_range_infos.as_ptr(),
91         );
92     }
93 
94     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdBuildAccelerationStructuresIndirectKHR.html>
95     #[inline]
cmd_build_acceleration_structures_indirect( &self, command_buffer: vk::CommandBuffer, infos: &[vk::AccelerationStructureBuildGeometryInfoKHR], indirect_device_addresses: &[vk::DeviceAddress], indirect_strides: &[u32], max_primitive_counts: &[&[u32]], )96     pub unsafe fn cmd_build_acceleration_structures_indirect(
97         &self,
98         command_buffer: vk::CommandBuffer,
99         infos: &[vk::AccelerationStructureBuildGeometryInfoKHR],
100         indirect_device_addresses: &[vk::DeviceAddress],
101         indirect_strides: &[u32],
102         max_primitive_counts: &[&[u32]],
103     ) {
104         assert_eq!(infos.len(), indirect_device_addresses.len());
105         assert_eq!(infos.len(), indirect_strides.len());
106         assert_eq!(infos.len(), max_primitive_counts.len());
107 
108         let max_primitive_counts = max_primitive_counts
109             .iter()
110             .zip(infos.iter())
111             .map(|(cnt, info)| {
112                 assert_eq!(cnt.len(), info.geometry_count as usize);
113                 cnt.as_ptr()
114             })
115             .collect::<Vec<_>>();
116 
117         (self.fp.cmd_build_acceleration_structures_indirect_khr)(
118             command_buffer,
119             infos.len() as _,
120             infos.as_ptr(),
121             indirect_device_addresses.as_ptr(),
122             indirect_strides.as_ptr(),
123             max_primitive_counts.as_ptr(),
124         );
125     }
126 
127     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkBuildAccelerationStructuresKHR.html>
128     #[inline]
build_acceleration_structures( &self, deferred_operation: vk::DeferredOperationKHR, infos: &[vk::AccelerationStructureBuildGeometryInfoKHR], build_range_infos: &[&[vk::AccelerationStructureBuildRangeInfoKHR]], ) -> VkResult<()>129     pub unsafe fn build_acceleration_structures(
130         &self,
131         deferred_operation: vk::DeferredOperationKHR,
132         infos: &[vk::AccelerationStructureBuildGeometryInfoKHR],
133         build_range_infos: &[&[vk::AccelerationStructureBuildRangeInfoKHR]],
134     ) -> VkResult<()> {
135         assert_eq!(infos.len(), build_range_infos.len());
136 
137         let build_range_infos = build_range_infos
138             .iter()
139             .zip(infos.iter())
140             .map(|(range_info, info)| {
141                 assert_eq!(range_info.len(), info.geometry_count as usize);
142                 range_info.as_ptr()
143             })
144             .collect::<Vec<_>>();
145 
146         (self.fp.build_acceleration_structures_khr)(
147             self.handle,
148             deferred_operation,
149             infos.len() as _,
150             infos.as_ptr(),
151             build_range_infos.as_ptr(),
152         )
153         .result()
154     }
155 
156     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCopyAccelerationStructureKHR.html>
157     #[inline]
copy_acceleration_structure( &self, deferred_operation: vk::DeferredOperationKHR, info: &vk::CopyAccelerationStructureInfoKHR, ) -> VkResult<()>158     pub unsafe fn copy_acceleration_structure(
159         &self,
160         deferred_operation: vk::DeferredOperationKHR,
161         info: &vk::CopyAccelerationStructureInfoKHR,
162     ) -> VkResult<()> {
163         (self.fp.copy_acceleration_structure_khr)(self.handle, deferred_operation, info).result()
164     }
165 
166     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCopyAccelerationStructureToMemoryKHR.html>
167     #[inline]
copy_acceleration_structure_to_memory( &self, deferred_operation: vk::DeferredOperationKHR, info: &vk::CopyAccelerationStructureToMemoryInfoKHR, ) -> VkResult<()>168     pub unsafe fn copy_acceleration_structure_to_memory(
169         &self,
170         deferred_operation: vk::DeferredOperationKHR,
171         info: &vk::CopyAccelerationStructureToMemoryInfoKHR,
172     ) -> VkResult<()> {
173         (self.fp.copy_acceleration_structure_to_memory_khr)(self.handle, deferred_operation, info)
174             .result()
175     }
176 
177     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCopyMemoryToAccelerationStructureKHR.html>
178     #[inline]
copy_memory_to_acceleration_structure( &self, deferred_operation: vk::DeferredOperationKHR, info: &vk::CopyMemoryToAccelerationStructureInfoKHR, ) -> VkResult<()>179     pub unsafe fn copy_memory_to_acceleration_structure(
180         &self,
181         deferred_operation: vk::DeferredOperationKHR,
182         info: &vk::CopyMemoryToAccelerationStructureInfoKHR,
183     ) -> VkResult<()> {
184         (self.fp.copy_memory_to_acceleration_structure_khr)(self.handle, deferred_operation, info)
185             .result()
186     }
187 
188     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkWriteAccelerationStructuresPropertiesKHR.html>
189     #[inline]
write_acceleration_structures_properties( &self, acceleration_structures: &[vk::AccelerationStructureKHR], query_type: vk::QueryType, data: &mut [u8], stride: usize, ) -> VkResult<()>190     pub unsafe fn write_acceleration_structures_properties(
191         &self,
192         acceleration_structures: &[vk::AccelerationStructureKHR],
193         query_type: vk::QueryType,
194         data: &mut [u8],
195         stride: usize,
196     ) -> VkResult<()> {
197         (self.fp.write_acceleration_structures_properties_khr)(
198             self.handle,
199             acceleration_structures.len() as _,
200             acceleration_structures.as_ptr(),
201             query_type,
202             data.len(),
203             data.as_mut_ptr().cast(),
204             stride,
205         )
206         .result()
207     }
208 
209     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdCopyAccelerationStructureKHR.html>
210     #[inline]
cmd_copy_acceleration_structure( &self, command_buffer: vk::CommandBuffer, info: &vk::CopyAccelerationStructureInfoKHR, )211     pub unsafe fn cmd_copy_acceleration_structure(
212         &self,
213         command_buffer: vk::CommandBuffer,
214         info: &vk::CopyAccelerationStructureInfoKHR,
215     ) {
216         (self.fp.cmd_copy_acceleration_structure_khr)(command_buffer, info);
217     }
218 
219     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdCopyAccelerationStructureToMemoryKHR.html>
220     #[inline]
cmd_copy_acceleration_structure_to_memory( &self, command_buffer: vk::CommandBuffer, info: &vk::CopyAccelerationStructureToMemoryInfoKHR, )221     pub unsafe fn cmd_copy_acceleration_structure_to_memory(
222         &self,
223         command_buffer: vk::CommandBuffer,
224         info: &vk::CopyAccelerationStructureToMemoryInfoKHR,
225     ) {
226         (self.fp.cmd_copy_acceleration_structure_to_memory_khr)(command_buffer, info);
227     }
228 
229     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdCopyMemoryToAccelerationStructureKHR.html>
230     #[inline]
cmd_copy_memory_to_acceleration_structure( &self, command_buffer: vk::CommandBuffer, info: &vk::CopyMemoryToAccelerationStructureInfoKHR, )231     pub unsafe fn cmd_copy_memory_to_acceleration_structure(
232         &self,
233         command_buffer: vk::CommandBuffer,
234         info: &vk::CopyMemoryToAccelerationStructureInfoKHR,
235     ) {
236         (self.fp.cmd_copy_memory_to_acceleration_structure_khr)(command_buffer, info);
237     }
238 
239     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetAccelerationStructureHandleKHR.html>
240     #[inline]
get_acceleration_structure_device_address( &self, info: &vk::AccelerationStructureDeviceAddressInfoKHR, ) -> vk::DeviceAddress241     pub unsafe fn get_acceleration_structure_device_address(
242         &self,
243         info: &vk::AccelerationStructureDeviceAddressInfoKHR,
244     ) -> vk::DeviceAddress {
245         (self.fp.get_acceleration_structure_device_address_khr)(self.handle, info)
246     }
247 
248     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdWriteAccelerationStructuresPropertiesKHR.html>
249     #[inline]
cmd_write_acceleration_structures_properties( &self, command_buffer: vk::CommandBuffer, structures: &[vk::AccelerationStructureKHR], query_type: vk::QueryType, query_pool: vk::QueryPool, first_query: u32, )250     pub unsafe fn cmd_write_acceleration_structures_properties(
251         &self,
252         command_buffer: vk::CommandBuffer,
253         structures: &[vk::AccelerationStructureKHR],
254         query_type: vk::QueryType,
255         query_pool: vk::QueryPool,
256         first_query: u32,
257     ) {
258         (self.fp.cmd_write_acceleration_structures_properties_khr)(
259             command_buffer,
260             structures.len() as _,
261             structures.as_ptr(),
262             query_type,
263             query_pool,
264             first_query,
265         );
266     }
267 
268     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDeviceAccelerationStructureCompatibilityKHR.html>
269     #[inline]
get_device_acceleration_structure_compatibility( &self, version: &vk::AccelerationStructureVersionInfoKHR, ) -> vk::AccelerationStructureCompatibilityKHR270     pub unsafe fn get_device_acceleration_structure_compatibility(
271         &self,
272         version: &vk::AccelerationStructureVersionInfoKHR,
273     ) -> vk::AccelerationStructureCompatibilityKHR {
274         let mut compatibility = vk::AccelerationStructureCompatibilityKHR::default();
275 
276         (self.fp.get_device_acceleration_structure_compatibility_khr)(
277             self.handle,
278             version,
279             &mut compatibility,
280         );
281 
282         compatibility
283     }
284 
285     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetAccelerationStructureBuildSizesKHR.html>
286     #[inline]
get_acceleration_structure_build_sizes( &self, build_type: vk::AccelerationStructureBuildTypeKHR, build_info: &vk::AccelerationStructureBuildGeometryInfoKHR, max_primitive_counts: &[u32], ) -> vk::AccelerationStructureBuildSizesInfoKHR287     pub unsafe fn get_acceleration_structure_build_sizes(
288         &self,
289         build_type: vk::AccelerationStructureBuildTypeKHR,
290         build_info: &vk::AccelerationStructureBuildGeometryInfoKHR,
291         max_primitive_counts: &[u32],
292     ) -> vk::AccelerationStructureBuildSizesInfoKHR {
293         assert_eq!(max_primitive_counts.len(), build_info.geometry_count as _);
294 
295         let mut size_info = vk::AccelerationStructureBuildSizesInfoKHR::default();
296 
297         (self.fp.get_acceleration_structure_build_sizes_khr)(
298             self.handle,
299             build_type,
300             build_info,
301             max_primitive_counts.as_ptr(),
302             &mut size_info,
303         );
304 
305         size_info
306     }
307 
308     #[inline]
name() -> &'static CStr309     pub const fn name() -> &'static CStr {
310         vk::KhrAccelerationStructureFn::name()
311     }
312 
313     #[inline]
fp(&self) -> &vk::KhrAccelerationStructureFn314     pub fn fp(&self) -> &vk::KhrAccelerationStructureFn {
315         &self.fp
316     }
317 
318     #[inline]
device(&self) -> vk::Device319     pub fn device(&self) -> vk::Device {
320         self.handle
321     }
322 }
323