use super::types::{Dx12State, SamplerState};
use super::utils;
use super::{DeviceHandle, SamplerHandle};
use crate::types::SamplerDesc;
use anyhow::{Context, Result};
use windows::Win32::Graphics::Direct3D12::*;
pub(super) fn create(state: &mut Dx12State, device_handle: DeviceHandle, desc: &SamplerDesc) -> Result<SamplerHandle> {
let handle = state.samplers.write().unwrap().alloc_handle();
let logical_device = state.devices.get(&device_handle).context("Invalid device handle")?;
let sampler_offset = logical_device
.descriptors
.lock()
.unwrap()
.resource_registry
.register_sampler(handle);
let sampler_desc = D3D12_SAMPLER_DESC {
Filter: utils::filter_to_d3d12(desc.min_filter, desc.mag_filter, desc.mipmap_filter),
AddressU: utils::address_mode_to_d3d12(desc.address_mode_u),
AddressV: utils::address_mode_to_d3d12(desc.address_mode_v),
AddressW: utils::address_mode_to_d3d12(desc.address_mode_w),
MipLODBias: 0.0,
MaxAnisotropy: desc.max_anisotropy as u32,
ComparisonFunc: desc
.compare
.map(utils::compare_to_d3d12)
.unwrap_or(D3D12_COMPARISON_FUNC_ALWAYS),
BorderColor: [0.0, 0.0, 0.0, 0.0],
MinLOD: desc.lod_min_clamp,
MaxLOD: desc.lod_max_clamp,
};
let sampler_cpu_handle = unsafe {
let mut handle = logical_device.sampler_heap.GetCPUDescriptorHandleForHeapStart();
handle.ptr += (sampler_offset * logical_device.sampler_descriptor_size) as usize;
handle
};
unsafe {
logical_device.device.CreateSampler(&sampler_desc, sampler_cpu_handle);
}
state.samplers.write().unwrap().entries.insert(
handle,
SamplerState {
device_handle,
sampler_offset,
desc: desc.clone(),
bindless_offset: Some(sampler_offset), },
);
tracing::debug!("Created sampler (handle={})", handle);
Ok(handle)
}
pub(super) fn destroy(state: &mut Dx12State, sampler_handle: SamplerHandle) {
if let Some(sampler) = state.samplers.write().unwrap().entries.remove(&sampler_handle) {
if let Some(ld) = state.devices.get(&sampler.device_handle) {
ld.descriptors.lock().unwrap().reclaim_sampler_slots(sampler_handle);
}
}
}
pub(super) fn bindless_index(state: &Dx12State, sampler_handle: SamplerHandle) -> Option<u32> {
state
.samplers
.read()
.unwrap()
.entries
.get(&sampler_handle)
.and_then(|s| s.bindless_offset)
}