use ash::vk;
use concinnity_core::render::error::RenderResult;
use concinnity_core::render::post::ssgi::settings::SsgiSettings;
use concinnity_core::render::post::ssgi::{SsgiInputs, SsgiPass, SsgiPipelines};
use crate::vulkan::context::VkContext;
use crate::vulkan::post::post_device::{PostPipeline, PostTarget, VkPostDevice, post_extent};
pub(in crate::vulkan) struct SsgiResources {
pub(in crate::vulkan) settings: SsgiSettings,
pass: SsgiPass<PostPipeline, PostTarget>,
}
impl SsgiResources {
pub(in crate::vulkan) fn new(
device: &VkPostDevice,
settings: SsgiSettings,
extent: vk::Extent2D,
) -> RenderResult<Self> {
Ok(Self {
settings,
pass: SsgiPass::new(device, settings.gi_scale, post_extent(extent))?,
})
}
pub(in crate::vulkan) fn rebuild(
&mut self,
device: &VkPostDevice,
extent: vk::Extent2D,
) -> RenderResult<()> {
self.pass.resize(device, post_extent(extent))
}
pub(in crate::vulkan) fn swap_pipelines(&mut self, pipelines: SsgiPipelines<PostPipeline>) {
self.pass.swap_pipelines(pipelines);
}
pub(in crate::vulkan) fn advance(&mut self) {
self.pass.advance();
}
pub(in crate::vulkan) fn reset_history(&mut self) {
self.pass.reset_history();
}
}
impl VkContext {
pub(in crate::vulkan) fn encode_ssgi(
&self,
cmd: vk::CommandBuffer,
frame_idx: usize,
fov_y_radians: f32,
aspect: f32,
) {
let Some(ssgi) = &self.ssgi else { return };
let Some(gbuffer) = self.gbuffer_targets().and_then(|gb| gb.frame(frame_idx)) else {
return;
};
let params = ssgi
.settings
.params(fov_y_radians, aspect, ssgi.pass.frame());
let device = self.post_device(frame_idx);
let scene = self.hdr_scene_attachment(frame_idx);
if let Err(e) = ssgi.pass.encode(
&device,
&cmd,
SsgiInputs {
scene: scene.view,
scene_target: scene,
normal_depth: gbuffer.normal_depth,
velocity: gbuffer.velocity,
},
¶ms,
) {
tracing::error!("SSGI: {e}");
}
}
}