gpt4 book ai didi

c++ - Direct2D 和 Direct3D 互操作性的方法

转载 作者:行者123 更新时间:2023-12-05 04:43:31 26 4
gpt4 key购买 nike

我想制作一个 Direct2D GUI,它将在 DLL 上运行,并将使用我注入(inject)其中的应用程序的 Direct3D 呈现。

我知道我可以简单地使用 ID2D1Factory::CreateDxgiSurfaceRenderTarget 制作 DXGI 表面并将其用作 d2d 渲染目标,但这需要在 Direct3D 上启用标志 D3D11_CREATE_DEVICE_BGRA_SUPPORT设备。

问题是应用程序在没有启用此标志的情况下创建其设备,因此,ID2D1Factory::CreateDxgiSurfaceRenderTarget 失败。

我正在尝试寻找另一种在应用程序窗口(外部或内部窗口的渲染目标)上绘制的方法,如果该窗口处于全屏状态,它也可以工作。

到目前为止,我尝试了这些替代方案:

  1. 使用 ID2D1Factory::CreateDCRenderTarget 创建一个 d2d 渲染目标。这行得通,但我渲染的部分是闪烁/闪烁(循环显示和隐藏非常快)。我还在 ID2D1RenderTarget::BeginDraw 之前调用了 ID2D1DCRenderTarget::BindDC,但它只是闪烁但少了一点,所以我仍然遇到同样的问题。

  2. 创建一个始终位于所有其他窗口顶部的新窗口,并使用 d2d 在那里呈现,但是,如果应用程序进入全屏模式,则该窗口不会显示在屏幕上。

  3. 创建第二个启用 D3D11_CREATE_DEVICE_BGRA_SUPPORT 标志的 D3D 设备,并在窗口设备和我自己的设备之间共享一个 ID3D11Texture2D 资源,但我没有能够让它工作......关于如何做到这一点的例子并不多。我的想法是创建第二个设备,在该设备上使用 d2d 进行绘制,然后同步 2 个 D3D 设备——我遵循了 this example (使用 direct11)。

  4. 创建一个D2D设备并将d2d设备的数据共享给d3d设备;但是,当我调用 ID2D1Factory1::CreateDevice 创 build 备时,它失败了,因为 D3D 设备是在没有启用 D3D11_CREATE_DEVICE_BGRA_SUPPORT 标志的情况下创建的。我从 this example 开始.

我听说过硬件覆盖,但它只适用于某些显卡,我想我会遇到这个问题 https://learn.microsoft.com/el-gr/windows/win32/medfound/hardware-overlay-support .

我目前正处于死胡同;我不知道该怎么办。有没有人有任何想法可以帮助我?

也许有什么方法可以在屏幕上绘图并且即使窗口处于全屏状态也能工作?

最佳答案

#3 是正确的。这里有一些提示。

不要使用键控互斥体。不要使用 NT 句柄。您唯一需要的标志是 D3D11_RESOURCE_MISC_SHARED

要跨设备正确同步对共享纹理的访问,请使用查询。具体来说,您需要类型为 D3D11_QUERY_EVENT 的查询。工作流程应如下所示。

  1. 在一台设备上创建共享纹理,在另一台设备上打开。它的创建位置和导入位置无关紧要。不要忘记 D3D11_BIND_RENDER_TARGET 标志。同时创建一个查询。

  2. 使用共享纹理的 CreateDxgiSurfaceRenderTarget 创建 D2D 设备,使用 D2D 和/或 DirectWrite 将叠加层渲染到共享纹理中。

  3. 在用于 D2D 渲染的带有 BGRA 标志的直接 D3D 设备上下文中,调用 ID3D11DeviceContext.End 一次,传递查询。然后等待 ID3D11DeviceContext.GetData 返回 S_OK。如果您关心电力/热能,请使用 Sleep(1),或者如果您优先考虑延迟,请使用 _mm_pause() 指令忙等待。

  4. 一旦 ID3D11DeviceContext.GetData 为该查询返回 S_OK,GPU 就完成了 2D 场景的渲染。您现在可以在另一台设备上使用该纹理来合成 3D 场景。

将 2D 内容组合到渲染目标中的方式取决于您想如何绘制 2D 内容。

如果那是一个小的不透明四边形,您可能可以CopySubresourceRegion到渲染目标纹理中。

或者,如果您的 2D 内容具有透明背景,您需要一个顶点+像素着色器来渲染一个四边形(4 个顶点)纹理与您的共享纹理。顺便说一句,你不一定需要顶点/索引缓冲区,有一个 well-known trick没有一个。不要忘记混合状态(您可能需要 alpha 混合)、深度/模板状态(您可能希望在渲染该四边形时禁用深度测试),还有共享纹理的 D3D11_BIND_SHADER_RESOURCE 标志。

附言还有另一种方法。确保您的代码在该进程创建其 Direct3D 设备之前在该进程中运行。然后使用类似 minhook 的东西拦截对 D3D11.dll::D3D11CreateDeviceAndSwapChain 的调用,在拦截的函数中设置您需要的 BGRA 位,然后调用原始函数。可靠性稍差,因为有多种方法可以创建 D3D 设备,但更容易实现,工作速度更快,使用的内存更少。

关于c++ - Direct2D 和 Direct3D 互操作性的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69589509/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com