假设有一个场景,其中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:写入交换链后台缓冲区的命令列表只能在与该缓冲区关联的命令队列上执行。 [STATE_SETTING ERROR#907:EXECUTECOMMANDLISTS_WRONGSWAPCHAINBUFFERREFERENCE]
即使ID3D12CommandQueue :: ExecuteCommandLists也被挂钩,问题也无法解决,因为无法从命令队列中检索关联的交换链。
所以我的问题是,在可能发生挂钩之前交换链创建发生的情况下,建议的处理此问题的方法是什么?
答案 0 :(得分:1)
如果有人在这里寻找答案,我发现了什么。 没有正式的方法可以做到这一点,对于叠加渲染,推荐的方法是使用DirectComposition,但这会产生性能影响,这对于游戏叠加来说并不是很好。
调查内存有一个可能的解决方案,从交换链中获取CommandQueue,如下所示:
#ifdef _M_X64
size_t* pOffset = (size_t*)((BYTE*)swapChain + 216);
#else
size_t* pOffset = (size_t*)((BYTE*)swapChain + 132);
#endif
*(&_commandQueue) = reinterpret_cast<ID3D12CommandQueue*>(*pOffset);
显然不建议使用此解决方案,但如果有人只是想进行一些调试,它可能会有用。
我的最终解决方案是挂钩到一个使用CommandQueue的函数(我使用ExecuteCommandLists)并在那里获取指针并稍后使用它来渲染叠加层。它并不完全令人满意,但只要没有多个交换链就可以工作。