假设 DX12 被 Hook 用于叠加渲染的场景,看起来最好的 Hook 功能是 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( ... );
}

这会导致错误并随后移除设备。请参阅下面的错误消息。



即使 ID3D12CommandQueue::ExecuteCommandLists 也被 Hook ,问题也没有解决,因为也无法从命令队列中检索关联的交换链。

所以我的问题是,在可能发生 Hook 之前创建交换链的情况下,处理此问题的推荐方法是什么?

最佳答案

如果有人正在寻找答案,这就是我发现的。
没有官方方法可以做到这一点,对于叠加渲染,推荐的方法是使用 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)并在那里获取指针并稍后使用它来呈现叠加层。它并不完全令人满意,但只要没有多个交换链,它就可以工作。

关于directx - 如何从交换链中获取 DirectX 12 命令队列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36286425/

10-13 08:45