use concinnity_core::render::error::RenderResult;
use concinnity_core::render::post::device::PostExtent;
use concinnity_core::render::post::ssgi::settings::SsgiSettings;
use concinnity_core::render::post::ssgi::{SsgiPass, SsgiPipelines, SsgiTraceInputs};
use windows::Win32::Graphics::Direct3D12::*;
use crate::directx::context::DxContext;
use crate::directx::post::post_device::{DxPostDevice, PostPipeline, PostTarget};
use crate::directx::texture::transition_barrier;
pub(in crate::directx) struct SsgiResources {
pub(in crate::directx) settings: SsgiSettings,
pass: SsgiPass<PostPipeline, PostTarget>,
}
impl SsgiResources {
pub(in crate::directx) fn new(
device: &DxPostDevice,
width: u32,
height: u32,
settings: SsgiSettings,
) -> RenderResult<Self> {
Ok(Self {
settings,
pass: SsgiPass::new(device, settings.gi_scale, PostExtent { width, height })?,
})
}
pub(in crate::directx) fn resize_to(
&mut self,
device: &DxPostDevice,
width: u32,
height: u32,
) -> RenderResult<()> {
self.pass.resize(device, PostExtent { width, height })
}
pub(in crate::directx) fn swap_pipelines(&mut self, pipelines: SsgiPipelines<PostPipeline>) {
self.pass.swap_pipelines(pipelines);
}
pub(in crate::directx) fn advance(&mut self) {
self.pass.advance();
}
pub(in crate::directx) fn reset_history(&mut self) {
self.pass.reset_history();
}
}
impl DxContext {
pub(in crate::directx) fn encode_ssgi(
&self,
cmd: &ID3D12GraphicsCommandList,
frame_idx: usize,
fov_y_radians: f32,
aspect: f32,
) {
let Some(ssgi) = &self.ssgi else { return };
let Some(gbuffer) = &self.gbuffer else { return };
let params = ssgi
.settings
.params(fov_y_radians, aspect, ssgi.pass.frame());
let device = self.post_device(frame_idx);
let normal_depth = gbuffer.normal_depth_srv_gpu;
if let Err(e) = ssgi
.pass
.encode_pyramid(&device, cmd, normal_depth, ¶ms)
{
tracing::error!("SSGI: {e}");
return;
}
let borrow = |from, to| {
unsafe {
cmd.ResourceBarrier(&[transition_barrier(self.hdr_scene_target(), from, to)]);
}
};
borrow(
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
);
let traced = ssgi.pass.encode_trace(
&device,
cmd,
SsgiTraceInputs {
scene: self.targets.hdr.srv_gpu,
normal_depth,
velocity: gbuffer.velocity_srv_gpu,
},
¶ms,
);
borrow(
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET,
);
let result = traced.and_then(|()| {
ssgi.pass.encode_composite(
&device,
cmd,
self.hdr_scene_attachment(),
normal_depth,
¶ms,
)
});
if let Err(e) = result {
tracing::error!("SSGI: {e}");
}
}
}