假设 DX12 被挂钩以进行覆盖渲染的场景,看起来最好的挂钩函数是 IDXGISwapChain::Present,其方式与 DX11 相同。让这个函数挂钩交换链是可用的,并且可以从中检索设备以创建资源。鉴于这些资源,也可以记录渲染命令。当我们尝试执行渲染命令时会出现问题,因为没有选项可以从交换链中检索关联的命令队列,所以没有这样的:
CComPtr<ID3D12Device> pD3D12Device;
if (pSwapChain->GetDevice(__uuidof(ID3D12Device), (void**)(&pD3D12Device)) == S_OK)
{
pD3D12Device->GetCommandQueueForSwapChain( swapChain )->ExecuteCommandLists(…);
}
另一种选择是创建一个新的命令队列来执行,如下所示:
CComPtr<ID3D12Device> pD3D12Device;
if (pSwapChain->GetDevice(__uuidof(ID3D12Device), (void**)(&pD3D12Device)) == S_OK)
{
D3D12_COMMAND_QUEUE_DESC queue_desc = {};
queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
HRESULT commandQueueRes = _device->CreateCommandQueue( &queue_desc, IID_PPV_ARGS( &_commandQueue ) );
_commandQueue->ExecuteCommandLists( ... );
}
这会导致错误和随后的设备移除。请参阅下面的错误消息。
D3D12 错误:ID3D12CommandQueue::ExecuteCommandLists:写入交换链后台缓冲区的命令列表只能在与该缓冲区关联的命令队列上执行。[状态设置错误#907:EXECUTECOMMANDLISTS_WRONGSWAPCHAINBUFFERREFERENCE]
即使 ID3D12CommandQueue::ExecuteCommandLists 也被钩住,问题也没有解决,因为也无法从命令队列中检索关联的交换链。
所以我的问题是,在可能发生挂钩之前创建交换链的情况下,推荐的解决此问题的方法是什么?