How to identify and release D3D12/DXGI objects when using windows-rs crate?

45 views Asked by At

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?

0

There are 0 answers