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 RayTracingPipeline {
10     handle: vk::Device,
11     fp: vk::KhrRayTracingPipelineFn,
12 }
13 
14 impl RayTracingPipeline {
new(instance: &Instance, device: &Device) -> Self15     pub fn new(instance: &Instance, device: &Device) -> Self {
16         let handle = device.handle();
17         let fp = vk::KhrRayTracingPipelineFn::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::PhysicalDeviceRayTracingPipelinePropertiesKHR24     pub unsafe fn get_properties(
25         instance: &Instance,
26         pdevice: vk::PhysicalDevice,
27     ) -> vk::PhysicalDeviceRayTracingPipelinePropertiesKHR {
28         let mut props_rt = vk::PhysicalDeviceRayTracingPipelinePropertiesKHR::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/vkCmdTraceRaysKHR.html>
37     #[inline]
cmd_trace_rays( &self, command_buffer: vk::CommandBuffer, raygen_shader_binding_tables: &vk::StridedDeviceAddressRegionKHR, miss_shader_binding_tables: &vk::StridedDeviceAddressRegionKHR, hit_shader_binding_tables: &vk::StridedDeviceAddressRegionKHR, callable_shader_binding_tables: &vk::StridedDeviceAddressRegionKHR, width: u32, height: u32, depth: u32, )38     pub unsafe fn cmd_trace_rays(
39         &self,
40         command_buffer: vk::CommandBuffer,
41         raygen_shader_binding_tables: &vk::StridedDeviceAddressRegionKHR,
42         miss_shader_binding_tables: &vk::StridedDeviceAddressRegionKHR,
43         hit_shader_binding_tables: &vk::StridedDeviceAddressRegionKHR,
44         callable_shader_binding_tables: &vk::StridedDeviceAddressRegionKHR,
45         width: u32,
46         height: u32,
47         depth: u32,
48     ) {
49         (self.fp.cmd_trace_rays_khr)(
50             command_buffer,
51             raygen_shader_binding_tables,
52             miss_shader_binding_tables,
53             hit_shader_binding_tables,
54             callable_shader_binding_tables,
55             width,
56             height,
57             depth,
58         );
59     }
60 
61     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateRayTracingPipelinesKHR.html>
62     #[inline]
create_ray_tracing_pipelines( &self, deferred_operation: vk::DeferredOperationKHR, pipeline_cache: vk::PipelineCache, create_info: &[vk::RayTracingPipelineCreateInfoKHR], allocation_callbacks: Option<&vk::AllocationCallbacks>, ) -> VkResult<Vec<vk::Pipeline>>63     pub unsafe fn create_ray_tracing_pipelines(
64         &self,
65         deferred_operation: vk::DeferredOperationKHR,
66         pipeline_cache: vk::PipelineCache,
67         create_info: &[vk::RayTracingPipelineCreateInfoKHR],
68         allocation_callbacks: Option<&vk::AllocationCallbacks>,
69     ) -> VkResult<Vec<vk::Pipeline>> {
70         let mut pipelines = vec![mem::zeroed(); create_info.len()];
71         (self.fp.create_ray_tracing_pipelines_khr)(
72             self.handle,
73             deferred_operation,
74             pipeline_cache,
75             create_info.len() as u32,
76             create_info.as_ptr(),
77             allocation_callbacks.as_raw_ptr(),
78             pipelines.as_mut_ptr(),
79         )
80         .result_with_success(pipelines)
81     }
82 
83     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetRayTracingShaderGroupHandlesKHR.html>
84     #[inline]
get_ray_tracing_shader_group_handles( &self, pipeline: vk::Pipeline, first_group: u32, group_count: u32, data_size: usize, ) -> VkResult<Vec<u8>>85     pub unsafe fn get_ray_tracing_shader_group_handles(
86         &self,
87         pipeline: vk::Pipeline,
88         first_group: u32,
89         group_count: u32,
90         data_size: usize,
91     ) -> VkResult<Vec<u8>> {
92         let mut data = Vec::<u8>::with_capacity(data_size);
93         (self.fp.get_ray_tracing_shader_group_handles_khr)(
94             self.handle,
95             pipeline,
96             first_group,
97             group_count,
98             data_size,
99             data.as_mut_ptr().cast(),
100         )
101         .result()?;
102         data.set_len(data_size);
103         Ok(data)
104     }
105 
106     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetRayTracingCaptureReplayShaderGroupHandlesKHR.html>
107     #[inline]
get_ray_tracing_capture_replay_shader_group_handles( &self, pipeline: vk::Pipeline, first_group: u32, group_count: u32, data_size: usize, ) -> VkResult<Vec<u8>>108     pub unsafe fn get_ray_tracing_capture_replay_shader_group_handles(
109         &self,
110         pipeline: vk::Pipeline,
111         first_group: u32,
112         group_count: u32,
113         data_size: usize,
114     ) -> VkResult<Vec<u8>> {
115         let mut data = Vec::<u8>::with_capacity(data_size);
116         (self
117             .fp
118             .get_ray_tracing_capture_replay_shader_group_handles_khr)(
119             self.handle,
120             pipeline,
121             first_group,
122             group_count,
123             data_size,
124             data.as_mut_ptr().cast(),
125         )
126         .result()?;
127         data.set_len(data_size);
128         Ok(data)
129     }
130 
131     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdTraceRaysIndirectKHR.html>
132     ///
133     /// `indirect_device_address` is a buffer device address which is a pointer to a [`vk::TraceRaysIndirectCommandKHR`] structure containing the trace ray parameters.
134     #[inline]
cmd_trace_rays_indirect( &self, command_buffer: vk::CommandBuffer, raygen_shader_binding_table: &[vk::StridedDeviceAddressRegionKHR], miss_shader_binding_table: &[vk::StridedDeviceAddressRegionKHR], hit_shader_binding_table: &[vk::StridedDeviceAddressRegionKHR], callable_shader_binding_table: &[vk::StridedDeviceAddressRegionKHR], indirect_device_address: vk::DeviceAddress, )135     pub unsafe fn cmd_trace_rays_indirect(
136         &self,
137         command_buffer: vk::CommandBuffer,
138         raygen_shader_binding_table: &[vk::StridedDeviceAddressRegionKHR],
139         miss_shader_binding_table: &[vk::StridedDeviceAddressRegionKHR],
140         hit_shader_binding_table: &[vk::StridedDeviceAddressRegionKHR],
141         callable_shader_binding_table: &[vk::StridedDeviceAddressRegionKHR],
142         indirect_device_address: vk::DeviceAddress,
143     ) {
144         (self.fp.cmd_trace_rays_indirect_khr)(
145             command_buffer,
146             raygen_shader_binding_table.as_ptr(),
147             miss_shader_binding_table.as_ptr(),
148             hit_shader_binding_table.as_ptr(),
149             callable_shader_binding_table.as_ptr(),
150             indirect_device_address,
151         );
152     }
153 
154     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetRayTracingShaderGroupStackSizeKHR.html>
155     #[inline]
get_ray_tracing_shader_group_stack_size( &self, pipeline: vk::Pipeline, group: u32, group_shader: vk::ShaderGroupShaderKHR, ) -> vk::DeviceSize156     pub unsafe fn get_ray_tracing_shader_group_stack_size(
157         &self,
158         pipeline: vk::Pipeline,
159         group: u32,
160         group_shader: vk::ShaderGroupShaderKHR,
161     ) -> vk::DeviceSize {
162         (self.fp.get_ray_tracing_shader_group_stack_size_khr)(
163             self.handle,
164             pipeline,
165             group,
166             group_shader,
167         )
168     }
169 
170     /// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCmdSetRayTracingPipelineStackSizeKHR.html>
171     #[inline]
cmd_set_ray_tracing_pipeline_stack_size( &self, command_buffer: vk::CommandBuffer, pipeline_stack_size: u32, )172     pub unsafe fn cmd_set_ray_tracing_pipeline_stack_size(
173         &self,
174         command_buffer: vk::CommandBuffer,
175         pipeline_stack_size: u32,
176     ) {
177         (self.fp.cmd_set_ray_tracing_pipeline_stack_size_khr)(command_buffer, pipeline_stack_size);
178     }
179 
180     #[inline]
name() -> &'static CStr181     pub const fn name() -> &'static CStr {
182         vk::KhrRayTracingPipelineFn::name()
183     }
184 
185     #[inline]
fp(&self) -> &vk::KhrRayTracingPipelineFn186     pub fn fp(&self) -> &vk::KhrRayTracingPipelineFn {
187         &self.fp
188     }
189 
190     #[inline]
device(&self) -> vk::Device191     pub fn device(&self) -> vk::Device {
192         self.handle
193     }
194 }
195