use concinnity_core::gfx::view_modes::ViewMode;
use concinnity_core::render::error::RenderResult;
use concinnity_core::render::pass_timing;
use concinnity_core::render::render_graph::PassId;
use concinnity_core::render::sky;
use windows::Win32::Graphics::Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
use windows::Win32::Graphics::Direct3D12::{
D3D12_QUERY_TYPE_TIMESTAMP, ID3D12Device, ID3D12GraphicsCommandList, ID3D12PipelineState,
ID3D12RootSignature,
};
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_D32_FLOAT;
use super::builtin_shaders::{self, CompileProgram};
use super::context::DxContext;
use super::descriptor_slot::DescriptorTables;
use super::pso::{Blend, Depth, GraphicsPso, Raster};
use super::root_sig::{RootSig, SamplerState, Visibility};
use super::texture::HDR_FORMAT;
pub(in crate::directx) struct DxSky {
root_sig: ID3D12RootSignature,
pso: ID3D12PipelineState,
background: bool,
}
impl DxSky {
pub(in crate::directx) fn build(
device: &ID3D12Device,
msaa_samples: u32,
background: bool,
hot_reload: bool,
) -> RenderResult<Self> {
let root_sig = RootSig::new()
.cbv(0, Visibility::All)
.srv_table(0, 1, Visibility::Pixel)
.static_sampler(SamplerState::LinearClamp, 0, Visibility::Pixel)
.build(device, "sky root sig")?;
let pso = build_sky_pso(device, &root_sig, msaa_samples, hot_reload)?;
Ok(Self {
root_sig,
pso,
background,
})
}
pub(in crate::directx) fn root_sig(&self) -> &ID3D12RootSignature {
&self.root_sig
}
pub(in crate::directx) fn swap_pso(&mut self, pso: ID3D12PipelineState) {
self.pso = pso;
}
}
pub(in crate::directx) fn build_sky_pso(
device: &ID3D12Device,
root_sig: &ID3D12RootSignature,
msaa_samples: u32,
hot_reload: bool,
) -> RenderResult<ID3D12PipelineState> {
let vs = builtin_shaders::SKY_VERT.compile(hot_reload)?;
let ps = builtin_shaders::SKY_FRAG.compile(hot_reload)?;
GraphicsPso::fullscreen(root_sig, &vs, &ps, HDR_FORMAT, Blend::Opaque)
.depth(DXGI_FORMAT_D32_FLOAT, Depth::read_only())
.samples(msaa_samples.max(1))
.raster(Raster {
multisample: msaa_samples > 1,
..Raster::default()
})
.build(device, "sky")
}
impl DxContext {
pub(in crate::directx) fn draws_sky(&self, mode: ViewMode) -> bool {
sky::draws_sky(
self.scene.env_map.prefilter_mip_count > 0,
self.sky.background,
mode,
)
}
pub(in crate::directx) fn encode_sky(&self, cmd: &ID3D12GraphicsCommandList, view_gva: u64) {
unsafe {
cmd.SetPipelineState(&self.sky.pso);
cmd.SetGraphicsRootSignature(&self.sky.root_sig);
cmd.SetGraphicsRootConstantBufferView(0, view_gva);
cmd.set_graphics_srv_table(1, self.scene.env_map.prefilter.srv_gpu);
cmd.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
cmd.DrawInstanced(3, 1, 0, 0);
}
self.inc_draw_calls(1);
}
pub(in crate::directx) fn encode_main_sky(
&self,
cmd: &ID3D12GraphicsCommandList,
frame_idx: usize,
view_gva: u64,
) {
let (start, end) = pass_timing::pass_pair(frame_idx, PassId::Sky);
let heap = self.timestamps.query_heap.as_ref();
if let Some(heap) = heap {
unsafe { cmd.EndQuery(heap, D3D12_QUERY_TYPE_TIMESTAMP, start) };
}
self.encode_sky(cmd, view_gva);
if let Some(heap) = heap {
unsafe { cmd.EndQuery(heap, D3D12_QUERY_TYPE_TIMESTAMP, end) };
}
}
}