但是当屏幕上的渲染目标基于DXGI交换链时,我不太确定该如何实现。据我所知,每个窗口只能有一个交换链。因此,我只能有一个基于交换链的单个渲染目标。这意味着只能通过这个单一的渲染目标进行屏幕渲染。
如果我的上述假设是正确的,那么处理多线程渲染的最佳方法是什么?需要对屏幕目标进行串行访问吗?工作线程是否应共享单个多线程d2d工厂?如果有适当的锁定机制,屏幕目标的BeginDraw / EndDraw / Present是否可以在工作线程上执行(即没有创建屏幕目标的线程)?
非常感谢任何建议。谢谢。
我现在正在处理同样的问题!根据我在MSDN上的阅读,最好的方法是:
即使遵循上述建议,我仍然没有得到一个可靠的多线程Direct2D函数集,所以这是我目前知道的所有信息 - 我还不知道其他确定存在的注意事项等等。
一些有用的关键部分:
You can create a multithreaded Direct2D factory instance. You can use and share a multithreaded factory and all it's resources from more than one thread, but accesses to those resources (via Direct2D calls) are serialized by Direct2D, so no access conflicts occur. If your app calls only Direct2D APIs, such protection is automatically done by Direct2D in a granular level with minimum overhead.
ID2D1Factory* m_D2DFactory; // Create a Direct2D factory. HRESULT hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_MULTI_THREADED, &m_D2DFactory );
还有一个非常重要的警告:
多线程考虑事项
在使用DXGI的应用程序中,如果有多个线程,需要小心避免死锁,即两个不同的线程互相等待。这种情况可能发生在以下两种情况下:
- 渲染线程不是消息泵线程。
- 执行DXGI API的线程与创建窗口的线程不同。
注意,在使用全屏交换链时,永远不要让消息泵线程等待渲染线程。例如,从渲染线程调用IDXGISwapChain1::Present1可能会导致渲染线程等待消息泵线程。当模式更改发生时,如果Present1调用::SetWindowPos()或::SetWindowStyle()并且其中任何一种方法调用了::SendMessage(),则此场景是可能发生的。在这种情况下,如果消息泵线程具有关键部分保护或者渲染线程被阻塞,那么两个线程将会死锁。