d3d12: Propagate descriptor heap and handle allocation errors (#5065)

This commit is contained in:
Nicolas Silva 2024-01-15 16:43:30 +01:00 committed by GitHub
parent 1da093f7d6
commit 445fa6019b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 53 deletions

View File

@ -117,32 +117,40 @@ struct FixedSizeHeap {
}
impl FixedSizeHeap {
fn new(device: &d3d12::Device, ty: d3d12::DescriptorHeapType) -> Self {
let (heap, _hr) = device.create_descriptor_heap(
HEAP_SIZE_FIXED as _,
ty,
d3d12::DescriptorHeapFlags::empty(),
0,
);
fn new(
device: &d3d12::Device,
ty: d3d12::DescriptorHeapType,
) -> Result<Self, crate::DeviceError> {
let heap = device
.create_descriptor_heap(
HEAP_SIZE_FIXED as _,
ty,
d3d12::DescriptorHeapFlags::empty(),
0,
)
.into_device_result("Descriptor heap creation")?;
Self {
Ok(Self {
handle_size: device.get_descriptor_increment_size(ty) as _,
availability: !0, // all free!
start: heap.start_cpu_descriptor(),
_raw: heap,
}
})
}
fn alloc_handle(&mut self) -> d3d12::CpuDescriptor {
fn alloc_handle(&mut self) -> Result<d3d12::CpuDescriptor, crate::DeviceError> {
// Find first free slot.
let slot = self.availability.trailing_zeros() as usize;
assert!(slot < HEAP_SIZE_FIXED);
if slot >= HEAP_SIZE_FIXED {
log::error!("Failed to allocate a handle form a fixed size heap");
return Err(crate::DeviceError::OutOfMemory);
}
// Set the slot as occupied.
self.availability ^= 1 << slot;
d3d12::CpuDescriptor {
Ok(d3d12::CpuDescriptor {
ptr: self.start.ptr + self.handle_size * slot,
}
})
}
fn free_handle(&mut self, handle: d3d12::CpuDescriptor) {
@ -189,29 +197,29 @@ impl CpuPool {
}
}
pub(super) fn alloc_handle(&mut self) -> Handle {
pub(super) fn alloc_handle(&mut self) -> Result<Handle, crate::DeviceError> {
let heap_index = self
.avaliable_heap_indices
.iter()
.next()
.unwrap_or_else(|| {
// Allocate a new heap
let id = self.heaps.len();
self.heaps.push(FixedSizeHeap::new(&self.device, self.ty));
self.avaliable_heap_indices.insert(id);
id
});
.unwrap_or(self.heaps.len());
// Allocate a new heap
if heap_index == self.heaps.len() {
self.heaps.push(FixedSizeHeap::new(&self.device, self.ty)?);
self.avaliable_heap_indices.insert(heap_index);
}
let heap = &mut self.heaps[heap_index];
let handle = Handle {
raw: heap.alloc_handle(),
raw: heap.alloc_handle()?,
heap_index,
};
if heap.is_full() {
self.avaliable_heap_indices.remove(heap_index);
}
handle
Ok(handle)
}
pub(super) fn free_handle(&mut self, handle: Handle) {

View File

@ -138,7 +138,7 @@ impl super::Device {
};
let mut rtv_pool = descriptor::CpuPool::new(raw.clone(), d3d12::DescriptorHeapType::Rtv);
let null_rtv_handle = rtv_pool.alloc_handle();
let null_rtv_handle = rtv_pool.alloc_handle()?;
// A null pResource is used to initialize a null descriptor,
// which guarantees D3D11-like null binding behavior (reading 0s, writes are discarded)
raw.create_render_target_view(
@ -476,43 +476,47 @@ impl crate::Device<super::Api> for super::Device {
texture.calc_subresource(desc.range.base_mip_level, desc.range.base_array_layer, 0),
),
handle_srv: if desc.usage.intersects(crate::TextureUses::RESOURCE) {
let raw_desc = unsafe { view_desc.to_srv() };
raw_desc.map(|raw_desc| {
let handle = self.srv_uav_pool.lock().alloc_handle();
unsafe {
self.raw.CreateShaderResourceView(
texture.resource.as_mut_ptr(),
&raw_desc,
handle.raw,
)
};
handle
})
match unsafe { view_desc.to_srv() } {
Some(raw_desc) => {
let handle = self.srv_uav_pool.lock().alloc_handle()?;
unsafe {
self.raw.CreateShaderResourceView(
texture.resource.as_mut_ptr(),
&raw_desc,
handle.raw,
)
};
Some(handle)
}
None => None,
}
} else {
None
},
handle_uav: if desc.usage.intersects(
crate::TextureUses::STORAGE_READ | crate::TextureUses::STORAGE_READ_WRITE,
) {
let raw_desc = unsafe { view_desc.to_uav() };
raw_desc.map(|raw_desc| {
let handle = self.srv_uav_pool.lock().alloc_handle();
unsafe {
self.raw.CreateUnorderedAccessView(
texture.resource.as_mut_ptr(),
ptr::null_mut(),
&raw_desc,
handle.raw,
)
};
handle
})
match unsafe { view_desc.to_uav() } {
Some(raw_desc) => {
let handle = self.srv_uav_pool.lock().alloc_handle()?;
unsafe {
self.raw.CreateUnorderedAccessView(
texture.resource.as_mut_ptr(),
ptr::null_mut(),
&raw_desc,
handle.raw,
);
}
Some(handle)
}
None => None,
}
} else {
None
},
handle_rtv: if desc.usage.intersects(crate::TextureUses::COLOR_TARGET) {
let raw_desc = unsafe { view_desc.to_rtv() };
let handle = self.rtv_pool.lock().alloc_handle();
let handle = self.rtv_pool.lock().alloc_handle()?;
unsafe {
self.raw.CreateRenderTargetView(
texture.resource.as_mut_ptr(),
@ -529,7 +533,7 @@ impl crate::Device<super::Api> for super::Device {
.intersects(crate::TextureUses::DEPTH_STENCIL_READ)
{
let raw_desc = unsafe { view_desc.to_dsv(true) };
let handle = self.dsv_pool.lock().alloc_handle();
let handle = self.dsv_pool.lock().alloc_handle()?;
unsafe {
self.raw.CreateDepthStencilView(
texture.resource.as_mut_ptr(),
@ -546,7 +550,7 @@ impl crate::Device<super::Api> for super::Device {
.intersects(crate::TextureUses::DEPTH_STENCIL_WRITE)
{
let raw_desc = unsafe { view_desc.to_dsv(false) };
let handle = self.dsv_pool.lock().alloc_handle();
let handle = self.dsv_pool.lock().alloc_handle()?;
unsafe {
self.raw.CreateDepthStencilView(
texture.resource.as_mut_ptr(),
@ -588,7 +592,7 @@ impl crate::Device<super::Api> for super::Device {
&self,
desc: &crate::SamplerDescriptor,
) -> Result<super::Sampler, crate::DeviceError> {
let handle = self.sampler_pool.lock().alloc_handle();
let handle = self.sampler_pool.lock().alloc_handle()?;
let reduction = match desc.compare {
Some(_) => d3d12_ty::D3D12_FILTER_REDUCTION_TYPE_COMPARISON,