use ash::vk;
use concinnity_core::render::error::RenderResult;
use concinnity_core::render::post::taa::{TaaInputs, TaaPass, TaaRing};
use crate::vulkan::context::VkContext;
use crate::vulkan::post::post_device::{PostPipeline, PostTarget, VkPostDevice, post_extent};
pub(in crate::vulkan) type VkTaaPass = TaaPass<PostPipeline, PostTarget>;
pub(in crate::vulkan) struct TaaResources {
pub(in crate::vulkan) pass: VkTaaPass,
pub(in crate::vulkan) taa_frame: u32,
}
impl TaaResources {
pub(in crate::vulkan) fn new(
device: &VkPostDevice,
frames: usize,
extent: vk::Extent2D,
) -> RenderResult<Self> {
Ok(Self {
pass: TaaPass::new(device, TaaRing::per_frame(frames), post_extent(extent))?,
taa_frame: 0,
})
}
pub(in crate::vulkan) fn output_view(&self, frame: usize) -> vk::ImageView {
self.pass.target(frame).view()
}
pub(in crate::vulkan) fn rebuild(
&mut self,
device: &VkPostDevice,
extent: vk::Extent2D,
) -> RenderResult<()> {
self.pass.resize(device, post_extent(extent))?;
self.taa_frame = 0;
Ok(())
}
pub(in crate::vulkan) fn swap_pipelines(&mut self, pipeline: PostPipeline) {
self.pass.swap_pipeline(pipeline);
}
}
impl VkContext {
pub(in crate::vulkan) fn encode_taa(
&self,
cmd: vk::CommandBuffer,
frame_idx: usize,
reactive_written: bool,
) {
let Some(taa) = &self.taa else { return };
let Some(velocity) = self.velocity_view_for_post(frame_idx) else {
tracing::error!("TAA enabled but the G-buffer velocity view is missing");
return;
};
let device = self.post_device(frame_idx);
if let Err(e) = taa.pass.encode(
&device,
&cmd,
frame_idx,
TaaInputs {
scene: self.post_scene_image(frame_idx).view,
velocity,
reactive: self
.reactive_mask(frame_idx)
.filter(|_| reactive_written)
.map(|m| m.view),
},
) {
tracing::error!("TAA resolve: {e}");
}
}
fn velocity_view_for_post(&self, frame: usize) -> Option<vk::ImageView> {
Some(self.gbuffer_targets()?.frame(frame)?.velocity)
}
}