如何将Direct3D内容渲染到ID2D1HwndRenderTarget中
解决方案与实践经验
针对你尝试的三类思路的明确答复
思路A:直接获取ID2D1HwndRenderTarget的底层表面
不存在公开的API可以从ID2D1HwndRenderTarget或其父类接口中提取底层IDXGISurface或ID3D11Texture2D实例。该接口是Windows 7时期推出的兼容层设计,主要为了简化GDI与Direct2D的互操作,底层渲染逻辑和资源完全不对外暴露,因此该方案完全不可行。
思路B:跨ID2D1设备绘制纹理
不同ID2D1Device创建的设备依赖资源默认不支持直接跨设备使用,你遇到的报错正是这个限制导致的。虽然可以通过给D3D纹理添加D3D11_RESOURCE_MISC_SHARED标志创建共享资源,再在目标D2D设备侧打开共享资源、重建位图的方式实现跨设备绘制,但操作流程复杂,且你无法获取ID2D1HwndRenderTarget内部绑定的D2D设备实例,因此该方案实现成本极高,不推荐使用。
思路C:CPU内存中转拷贝
如果必须使用ID2D1HwndRenderTarget作为渲染输出,这是唯一可行的方案。不过你可以优化使用场景:窗口调整大小的过程中不需要实时渲染3D内容,只需要将调整前的最后一帧3D内容拉伸绘制即可,这种场景下两次全纹理拷贝的开销极低,完全不会感知到性能问题。
更优的流畅窗口调整实现方案
你不需要切换到ID2D1HwndRenderTarget和重定向表面就能实现无延迟无闪烁的调整效果,目前行业内通用的实现方案如下:
- 拦截
WM_ENTERSIZEMOVE消息,进入窗口调整状态时,将当前最后一帧3D渲染结果保存到一份离屏D3D纹理中,不需要额外修改3D渲染逻辑 - 在窗口调整过程中响应
WM_SIZING消息,直接使用与你的D3D设备同源创建的ID2D1DeviceContext,将离屏纹理拉伸绘制到交换链的后台缓冲区,调用Present输出即可,拉伸操作的GPU开销可以忽略,完全不会出现卡顿 - 拦截
WM_EXITSIZEMOVE消息,退出窗口调整状态时,重建交换链到新的窗口尺寸,销毁临时离屏纹理,恢复正常的3D渲染路径
该方案完全避开了不同设备资源互操作的问题,不需要修改你现有基于翻转序列交换链的渲染逻辑,实现成本极低,且流畅度完全符合预期。
内容的提问来源于stack exchange,提问作者user1548418
相关产品推荐
相关产品推荐

