From 445fa6019b47079c9d336881dbee1c3be3ed4c38 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Mon, 15 Jan 2024 16:43:30 +0100 Subject: [PATCH] d3d12: Propagate descriptor heap and handle allocation errors (#5065) --- wgpu-hal/src/dx12/descriptor.rs | 54 ++++++++++++++++------------ wgpu-hal/src/dx12/device.rs | 64 +++++++++++++++++---------------- 2 files changed, 65 insertions(+), 53 deletions(-) diff --git a/wgpu-hal/src/dx12/descriptor.rs b/wgpu-hal/src/dx12/descriptor.rs index 2a6d545e7..8833c1adf 100644 --- a/wgpu-hal/src/dx12/descriptor.rs +++ b/wgpu-hal/src/dx12/descriptor.rs @@ -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 { + 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 { // 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 { 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) { diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 2346dff26..0c1977203 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -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 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 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 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 for super::Device { &self, desc: &crate::SamplerDescriptor, ) -> Result { - 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,