use ash::vk;
use concinnity_core::render::error::RenderResult;
use concinnity_core::render::post::reflection_composite::{
ReflectionCompositeInputs, ReflectionCompositePass,
};
use concinnity_core::render::post::reflection_path::ReflectionPath;
use super::super::context::VkContext;
use super::super::texture::GpuImage;
use crate::vulkan::post::post_device::{PostPipeline, PostTarget, VkPostDevice, post_extent};
pub(in crate::vulkan) type VkReflectionCompositePass =
ReflectionCompositePass<PostPipeline, PostTarget>;
pub(in crate::vulkan) fn build_reflection_composite(
device: &VkPostDevice,
blur_scale: u32,
extent: vk::Extent2D,
) -> RenderResult<VkReflectionCompositePass> {
ReflectionCompositePass::new(device, blur_scale, post_extent(extent))
}
impl VkContext {
pub(in crate::vulkan) fn reflection_path(&self) -> ReflectionPath {
ReflectionPath::new(
self.ssr_authored(),
self.rt_reflections.is_some(),
self.rt.accel.is_some(),
)
}
pub(in crate::vulkan) fn ssr_resolve_active(&self) -> bool {
self.reflection_path().ssr_resolve
}
pub(in crate::vulkan) fn post_scene_image(&self, frame: usize) -> &GpuImage {
match self.reflection_composite.as_ref() {
Some(rc) => rc.output().image(),
None => &self.targets.hdr_resolve_images[frame % self.targets.hdr_resolve_images.len()],
}
}
fn release_unfed_reflection_composite(&mut self) -> bool {
if self.reflection_path().composite || self.reflection_composite.is_none() {
return false;
}
self.post.cache.forget_views();
self.reflection_composite = None;
true
}
pub(in crate::vulkan) fn reconcile_reflection_composite(
&mut self,
blur_scale: u32,
) -> RenderResult<()> {
self.release_unfed_reflection_composite();
if !self.reflection_path().composite {
return Ok(());
}
if let Some(mut rc) = self.reflection_composite.take() {
if rc.blur_scale_differs(blur_scale) {
self.post.cache.forget_views();
}
let rescaled = rc.set_blur_scale(
&self.post_device(0),
blur_scale,
post_extent(self.targets.render_extent),
);
self.reflection_composite = Some(rc);
return rescaled.map(|_| ());
}
let rc = build_reflection_composite(
&self.post_device(0),
blur_scale,
self.targets.render_extent,
)?;
self.reflection_composite = Some(rc);
Ok(())
}
pub(in crate::vulkan) fn encode_reflection_composite(
&self,
cmd: vk::CommandBuffer,
reflection_view: vk::ImageView,
frame_idx: usize,
) {
let Some(rc) = &self.reflection_composite else {
return;
};
let Some(gbuffer) = self.gbuffer_targets().and_then(|gb| gb.frame(frame_idx)) else {
return;
};
let scene =
&self.targets.hdr_resolve_images[frame_idx % self.targets.hdr_resolve_images.len()];
if let Err(e) = rc.encode(
&self.post_device(frame_idx),
&cmd,
ReflectionCompositeInputs {
reflection: reflection_view,
scene: scene.view,
normal_depth: gbuffer.normal_depth,
roughness: gbuffer.roughness,
},
) {
tracing::error!("reflection composite: {e}");
}
}
}