How should I be destroying D3D12/DXGI objects in Rust using the windows-rs crate?
My very simple clears the screen app crashes on exit (info queue break on severity warning is set) with the following live objects:
dxgi live objects:
DXGI WARNING: Live IDXGIFactory at 0x00000248A9AED290, Refcount: 7 [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live IDXGIAdapter at 0x00000248AC47FD10, Refcount: 1 [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live IDXGIAdapter at 0x00000248B2CFCDA0, Refcount: 1 [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live IDXGIOutput at 0x00000248B2CFD230, Refcount: 1 [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live IDXGIAdapter at 0x00000248B2D00450, Refcount: 1 [ STATE_CREATION WARNING #0: ]
D3D12 WARNING: Live ID3D12Device at 0x00000248ABFF5FB8, Refcount: 19 [ STATE_CREATION WARNING #274: LIVE_DEVICE]
D3D12: **BREAK** enabled for the previous message, which was: [ WARNING STATE_CREATION #274: LIVE_DEVICE ]
I have all of my resources in an optional struct, much like in the windows-rs D3D12 sample, which I drop in the Drop
trait before the call to ReportLiveObjects
.
struct Resources {
#[allow(unused)]
device: ID3D12Device,
command_queue: ID3D12CommandQueue,
swap_chain: IDXGISwapChain3,
frame_index: usize,
rtv_heap: ID3D12DescriptorHeap,
rtv_descriptor_size: u32,
render_targets: Vec<ID3D12Resource>,
command_allocators: Vec<ID3D12CommandAllocator>,
command_list: ID3D12GraphicsCommandList,
fence: ID3D12Fence,
fence_value: u64,
fence_event: HANDLE,
frame_fence_values: Vec<u64>,
tearing_supported: bool,
}
impl Drop for D3D12Renderer {
fn drop(&mut self) {
unsafe {
if let Some(mut resources) = self.resources.take() {
debug_check!(flush(
&resources.command_queue,
&resources.fence,
&mut resources.fence_value,
&resources.fence_event,
)
.is_ok());
debug_check!(CloseHandle(resources.fence_event).is_ok());
}
if cfg!(debug_assertions) {
if let Ok(dxgi_debug) = DXGIGetDebugInterface1::<IDXGIDebug1>(0) {
OutputDebugStringW(PCWSTR(wstr!("dxgi live objects:\n").as_ptr()));
debug_check!(dxgi_debug
.ReportLiveObjects(
DXGI_DEBUG_ALL,
DXGI_DEBUG_RLO_DETAIL | DXGI_DEBUG_RLO_IGNORE_INTERNAL,
)
.is_ok());
}
}
}
println!("renderer shutdown");
}
}
There's a GitHub issue that asks a similar question, and it's suggested that manually dropping the transition barriers is required:
command_list.ResourceBarrier(&[barrier.clone()]);
let _: D3D12_RESOURCE_TRANSITION_BARRIER =
std::mem::ManuallyDrop::into_inner(barrier.Anonymous.Transition);
However, doing this does not change the Refcount from 19.
How am I supposed to identify and correctly release these objects?