use concinnity_core::render::backend_init::{PostSettings, SceneData};
use concinnity_core::render::error::RenderResult;
use super::InitGpu;
use crate::directx::context::{DxRayTracing, DxSceneAssets, DxTargets};
use crate::directx::post::post_device::DxPostDevice;
use crate::directx::post::reflection_composite::{
DxReflectionCompositePass, build_reflection_composite as build_composite,
};
use crate::directx::post::rt_reflections::{
RtBuildContext, RtBuildInit, RtOutputDescriptors, RtReflectionsResources,
};
use crate::directx::quality::QualitySlotHandles;
use crate::directx::raytrace;
use crate::directx::transparent::TransparentResources;
pub(super) fn build_reflection_composite(
device: &DxPostDevice,
targets: &DxTargets,
post: &PostSettings,
) -> RenderResult<Option<DxReflectionCompositePass>> {
if post.ssr.is_none() && post.rt_reflections.is_none() {
return Ok(None);
}
Ok(Some(build_composite(
device,
post.reflection_blur_scale,
targets.extent.render_width,
targets.extent.render_height,
)?))
}
pub(super) fn build_rt_reflections(
gpu: &InitGpu<'_>,
slots: &QualitySlotHandles,
targets: &DxTargets,
post: &PostSettings,
) -> Option<RtReflectionsResources> {
let hw = gpu.hw;
match (post.rt_reflections, hw.rt_capable) {
(Some(settings), true) => match RtReflectionsResources::new(
RtBuildContext {
alloc: &hw.alloc,
width: targets.extent.render_width,
height: targets.extent.render_height,
},
settings,
RtOutputDescriptors {
output_rtv: slots.rt_output_rtv,
output_srv: slots.rt_output_srv,
},
RtBuildInit {
info_queue: hw.info_queue.as_ref(),
hot_reload: gpu.hot_reload,
},
) {
Ok(r) => Some(r),
Err(e) => {
tracing::warn!("RT reflections unavailable, falling back to SSR: {e}");
None
}
},
_ => None,
}
}
pub(super) struct RtInputs<'a> {
pub(super) world: &'a SceneData<'a>,
pub(super) scene: &'a DxSceneAssets,
pub(super) reflections: Option<&'a RtReflectionsResources>,
pub(super) transparent: Option<&'a TransparentResources>,
pub(super) post: &'a PostSettings,
}
pub(super) fn build_ray_tracing(gpu: &InitGpu<'_>, inputs: RtInputs<'_>) -> DxRayTracing {
let RtInputs {
world,
scene,
reflections,
transparent,
post,
} = inputs;
let hw = gpu.hw;
let accel = if reflections.is_some() {
match raytrace::build_rt_accel(raytrace::RtInitGeometry {
alloc: &hw.alloc,
shared: raytrace::SharedGeometry::of(&scene.geometry),
draw_objects: &world.draw_objects,
clusters: &world.instanced_clusters,
albedo_count: scene.textures.len() as u32,
exclude_seethrough: transparent.is_some_and(|t| t.mesh_pipelines_ready()),
skinned_present: false,
}) {
Ok(accel) => accel,
Err(e) => {
tracing::warn!("RT acceleration-structure build failed, falling back to SSR: {e}");
None
}
}
} else {
None
};
let skin = reflections
.is_some()
.then(|| raytrace::build_rt_skin(&hw.device, gpu.hot_reload))
.flatten();
DxRayTracing {
accel,
dynamic_mode: post.rt_dynamic,
update_streak: Default::default(),
retired: Default::default(),
retire_tick: 0,
skinned_geometry: post.rt_skinned_geometry,
skin,
}
}