use concinnity_core::render::error::RenderResult;
use concinnity_core::render::post::bloom::{BloomPass, BloomPipelines, top_extent};
use concinnity_core::render::post::device::PostExtent;
use concinnity_core::render::render_graph::PixelFormat;
use windows::Win32::Graphics::Direct3D12::*;
use crate::directx::context::DxContext;
use crate::directx::descriptor_slot::SrvSlot;
use crate::directx::post::post_device::{DxPostDevice, PooledTarget, PostPipeline, PostTarget};
use crate::directx::texture::transition_barrier;
pub(in crate::directx) struct BloomResources {
pass: BloomPass<PostPipeline, PostTarget>,
top: PooledTarget,
}
impl BloomResources {
pub(in crate::directx) fn new(
device: &DxPostDevice,
output: PostExtent,
top: &ID3D12Resource,
) -> RenderResult<Self> {
Ok(Self {
pass: BloomPass::new(device, output)?,
top: view_top(device, output, top)?,
})
}
pub(in crate::directx) fn resize(
&mut self,
device: &DxPostDevice,
output: PostExtent,
top: &ID3D12Resource,
) -> RenderResult<()> {
self.pass.resize(device, output)?;
self.repoint_top(device, output, top)
}
pub(in crate::directx) fn repoint_top(
&mut self,
device: &DxPostDevice,
output: PostExtent,
top: &ID3D12Resource,
) -> RenderResult<()> {
self.top = view_top(device, output, top)?;
Ok(())
}
pub(in crate::directx) fn top_srv_gpu(&self) -> SrvSlot {
self.top.srv_gpu()
}
pub(in crate::directx) fn swap_pipelines(&mut self, pipelines: BloomPipelines<PostPipeline>) {
self.pass.swap_pipelines(pipelines);
}
}
fn view_top(
device: &DxPostDevice,
output: PostExtent,
top: &ID3D12Resource,
) -> RenderResult<PooledTarget> {
device.pooled_target(top, PixelFormat::Rgba16Float, top_extent(output))
}
impl DxContext {
pub(in crate::directx) fn encode_bloom(
&self,
cmd: &ID3D12GraphicsCommandList,
frame_idx: usize,
scene_srv: SrvSlot,
) -> RenderResult<()> {
let Some(bloom) = &self.bloom else {
return Ok(());
};
let device = self.post_device(frame_idx);
let (pass, bloom_top) = (&bloom.pass, &bloom.top);
pass.encode_prefilter(
&device,
cmd,
scene_srv,
bloom_top.attachment(),
&self.post_process,
)?;
let sampled = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
let target = D3D12_RESOURCE_STATE_RENDER_TARGET;
unsafe {
cmd.ResourceBarrier(&[transition_barrier(bloom_top.resource(), target, sampled)])
};
pass.encode_chain(&device, cmd, bloom_top.srv_gpu())?;
unsafe {
cmd.ResourceBarrier(&[transition_barrier(bloom_top.resource(), sampled, target)])
};
pass.encode_last_upsample(&device, cmd, bloom_top.attachment())
}
}