当使用相同的 HWND 时,D3D11CreateDeviceAndSwapChain 失败 E_ACCESSDENIED

D3D11CreateDeviceAndSwapChain Fails With E_ACCESSDENIED When Using Same HWND

如果我创建一个 window 并将 HWND 传递给 D3D11CreateDeviceAndSwapChain,它就可以工作。但是,在我释放设备、上下文、交换链等并尝试使用相同的 HWND 重复该过程后,D3D11CreateDeviceAndSwapChain 失败并返回 E_ACCESSDENIED。这告诉我一定有什么东西在 HWND 上,但是什么?我在 class 的析构函数中释放了所有全局变量。有人知道问题出在哪里吗?

~decoder()
    {
        m_VertexShader->Release();
        m_VertexShader = nullptr;

        m_PixelShader->Release();
        m_PixelShader = nullptr;

        m_InputLayout->Release();
        m_InputLayout = nullptr;

        device->Release();
        device = nullptr;

        context->Release();
        context = nullptr;

        swapchain->Release();
        swapchain = nullptr;

        rendertargetview->Release();
        rendertargetview = nullptr;

        m_SamplerLinear->Release();
        m_SamplerLinear = nullptr;

        HRESULT hr = S_OK;
        hr = decoder_transform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, NULL);
        hr = decoder_transform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, NULL);
        hr = decoder_transform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, NULL);

        decoder_transform.Release();
        color_transform.Release();

        hr = MFShutdown();
    }

虽然 D3D11CreateDeviceAbdSwapChain does not mention why this is happening in the documentation, it is essentially just a wrapper around creating a D3D11Device and swap chain. The documentation for IDXGIFactory2::CreateSwapChainForHwnd 确实详细说明了发生这种情况的原因。

Because you can associate only one flip presentation model swap chain at a time with an HWND, the Microsoft Direct3D 11 policy of deferring the destruction of objects can cause problems if you attempt to destroy a flip presentation model swap chain and replace it with another swap chain. For more info about this situation, see Deferred Destruction Issues with Flip Presentation Swap Chains.

有关 Deferred Destruction Issues with Flip Presentation Swap Chains advises calling ID3D11DeviceContext::ClearState followed by ID3D11DeviceContext::Flush 的文档。

However, if an application must actually destroy an old swap chain and create a new swap chain, the application must force the destruction of all objects that the application freed. To force the destruction, call ID3D11DeviceContext::ClearState (or otherwise ensure no views are bound to pipeline state), and then call Flush on the immediate context. You must force destruction before you call IDXGIFactory2::CreateSwapChainForHwnd, IDXGIFactory2::CreateSwapChainForCoreWindow, or IDXGIFactory2::CreateSwapChainForComposition again to create a new swap chain.