use {
super::{PipelineCommand, cmd_ref::CommandRef},
crate::driver::{device::Device, ray_tracing::RayTracingPipeline},
ash::vk,
std::ops::Deref,
};
impl PipelineCommand<'_, RayTracingPipeline> {
pub fn record_cmd(
mut self,
func: impl FnOnce(RayTracingCommandRef<'_>) + Send + 'static,
) -> Self {
self.record_cmd_mut(func);
self
}
pub fn record_cmd_mut(&mut self, func: impl FnOnce(RayTracingCommandRef<'_>) + Send + 'static) {
let pipeline = self
.cmd
.cmd()
.expect_last_pipeline()
.expect_ray_tracing()
.clone();
self.cmd.push_exec(move |cmd| {
func(RayTracingCommandRef { cmd, pipeline });
});
}
pub(crate) fn record_stream_mut(
&mut self,
func: impl for<'r> Fn(RayTracingCommandRef<'r>) + Send + Sync + 'static,
) {
let pipeline = self
.cmd
.cmd()
.expect_last_pipeline()
.expect_ray_tracing()
.clone();
self.cmd.push_reusable_exec(move |cmd| {
func(RayTracingCommandRef {
cmd,
pipeline: pipeline.clone(),
});
});
}
}
pub struct RayTracingCommandRef<'a> {
cmd: CommandRef<'a>,
pipeline: RayTracingPipeline,
}
impl RayTracingCommandRef<'_> {
#[profiling::function]
pub fn push_constants(&self, offset: u32, data: &[u8]) -> &Self {
self.cmd_push_constants(
self.pipeline.inner.layout,
&self.pipeline.inner.push_constants,
offset,
data,
);
self
}
#[profiling::function]
pub fn set_stack_size(&self, pipeline_stack_size: u32) -> &Self {
let khr_ray_tracing_pipeline = Device::expect_vk_khr_ray_tracing_pipeline(&self.cmd.device);
#[cfg(feature = "checked")]
assert!(
self.pipeline.inner.info.dynamic_stack_size,
"ray tracing pipeline was not created with dynamic_stack_size enabled"
);
unsafe {
khr_ray_tracing_pipeline
.cmd_set_ray_tracing_pipeline_stack_size(self.cmd.handle, pipeline_stack_size);
}
self
}
#[allow(clippy::too_many_arguments)]
#[profiling::function]
pub fn trace_rays(
&self,
raygen_shader_binding_table: &vk::StridedDeviceAddressRegionKHR,
miss_shader_binding_table: &vk::StridedDeviceAddressRegionKHR,
hit_shader_binding_table: &vk::StridedDeviceAddressRegionKHR,
callable_shader_binding_table: &vk::StridedDeviceAddressRegionKHR,
width: u32,
height: u32,
depth: u32,
) -> &Self {
let khr_ray_tracing_pipeline = Device::expect_vk_khr_ray_tracing_pipeline(&self.cmd.device);
unsafe {
khr_ray_tracing_pipeline.cmd_trace_rays(
self.cmd.handle,
raygen_shader_binding_table,
miss_shader_binding_table,
hit_shader_binding_table,
callable_shader_binding_table,
width,
height,
depth,
);
}
self
}
#[profiling::function]
pub fn trace_rays_indirect(
&self,
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,
) -> &Self {
let khr_ray_tracing_pipeline = Device::expect_vk_khr_ray_tracing_pipeline(&self.cmd.device);
unsafe {
khr_ray_tracing_pipeline.cmd_trace_rays_indirect(
self.cmd.handle,
raygen_shader_binding_table,
miss_shader_binding_table,
hit_shader_binding_table,
callable_shader_binding_table,
indirect_device_address,
)
}
self
}
}
impl<'a> Deref for RayTracingCommandRef<'a> {
type Target = CommandRef<'a>;
fn deref(&self) -> &Self::Target {
&self.cmd
}
}