use concinnity_core::render::error::RenderResult;
use windows::Win32::Graphics::Direct3D12::*;
use super::heap_layout::{RtvHeapLayout, SrvHeapLayout, SrvHeapParams};
use super::{InitGpu, heaps};
use crate::directx::context::{DxDescriptors, SwapchainState};
use crate::directx::descriptor_slot::{SamplerSlot, SrvSlot};
use crate::directx::error::map_hresult;
use crate::directx::post::descriptors::PostDescriptors;
pub(super) fn build_descriptors(
gpu: &InitGpu<'_>,
params: &SrvHeapParams,
anisotropy: u32,
) -> RenderResult<DxDescriptors> {
let device = &gpu.hw.device;
let layout = SrvHeapLayout::compute(params);
let srv_heap: ID3D12DescriptorHeap = unsafe {
device.CreateDescriptorHeap(&D3D12_DESCRIPTOR_HEAP_DESC {
Type: D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
NumDescriptors: layout.srv_slots as u32,
Flags: D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
..Default::default()
})
}
.map_err(|e| map_hresult(e.code(), "SRV heap"))?;
let srv_descriptor_size =
heaps::descriptor_size(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
let sampler_heap = heaps::create_sampler_heap(device, anisotropy)?;
let sampler_descriptor_size =
heaps::descriptor_size(device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
let sampler_gpu = |slot| SamplerSlot::at(&sampler_heap, sampler_descriptor_size, slot);
Ok(DxDescriptors {
shadow_sampler_gpu: sampler_gpu(heaps::SHADOW_SAMPLER_SLOT),
linear_sampler_gpu: sampler_gpu(heaps::LINEAR_SAMPLER_SLOT),
text_sampler_gpu: sampler_gpu(heaps::TEXT_SAMPLER_SLOT),
srv_heap,
srv_descriptor_size,
flat_pool_len: params.albedo_count + params.normal_count,
layout,
sampler_heap,
})
}
impl DxDescriptors {
pub(in crate::directx) fn slot_cpu(&self, slot: usize) -> D3D12_CPU_DESCRIPTOR_HANDLE {
heaps::cpu_handle(&self.srv_heap, self.srv_descriptor_size, slot)
}
pub(super) fn slot_gpu(&self, slot: usize) -> SrvSlot {
SrvSlot::at(&self.srv_heap, self.srv_descriptor_size, slot)
}
}
pub(super) fn build_post_descriptors(
descriptors: &DxDescriptors,
swapchain: &SwapchainState,
rtv: &RtvHeapLayout,
) -> PostDescriptors {
let post_srv_base_slot = descriptors.layout.post_srv_base_slot;
PostDescriptors::new(
descriptors.slot_cpu(post_srv_base_slot),
descriptors.slot_gpu(post_srv_base_slot),
descriptors.srv_descriptor_size,
swapchain.rtv(rtv.post_base_slot),
swapchain.rtv_descriptor_size,
)
}