Direct2D& amp;多线程的最佳实践是什么? DXGI(D3D互操作)?

时间:2011-06-05 11:52:43

标签: direct2d

理想情况下,我希望有多个工作线程能够渲染到屏幕外的渲染目标,然后将渲染的内容“传输”到屏幕上的目标。使用hwnd渲染目标,这似乎不是问题(msdn有一个例子)。

当屏幕渲染目标基于DXGI交换链时,我不太清楚如何做到这一点。据我所知,每个窗口只能有一个交换链。因此,我只能基于交换链拥有一个渲染目标。这意味着屏幕渲染只能通过单个渲染目标完成。

如果我的上述假设是正确的,那么处理多线程渲染的最佳方法是什么?我是否需要序列化对屏幕目标的访问?工作线程应该共享一个多线程d2d工厂吗?如果有适当的锁定机制,可以在工作线程(即没有创建屏幕目标的线程)上执行屏幕目标的BeginDraw / EndDraw / Present吗?

我很感激任何建议。 感谢。

2 个答案:

答案 0 :(得分:4)

我现在正在处理同样的问题!根据我在MSDN上的阅读,最好的方法是:

我还没有一套可靠的多线程Direct2D函数,即便如此,所以这就是我所知道的 - 我还不知道肯定存在的其他警告等。

一些有用的关键位:

  

您可以创建多线程Direct2D工厂实例。您可以使用   并分享一个多线程工厂及其所有资源   比一个线程,但访问这些资源(通过Direct2D调用)   由Direct2D序列化,因此不会发生访问冲突。如果你的应用程序   只调用Direct2D API,这样的保护是自动完成的   Direct2D在粒度级别,开销最小。

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()和这些方法中的任何一个调用   ::发信息()。在这种情况下,如果消息泵线程有一个   关键部分保护它或如果渲染线程被阻止,那么   两个线程将陷入僵局。

答案 1 :(得分:1)

对于屏幕外渲染目标,您可以创建单独的D2DFactories并将其附加到使用CreateWicBitmapRenderTarget或CreateDxgiSurfaceRenderTarget创建的相应屏幕外渲染目标。在将其传输到屏幕目标时,您必须等待所有线程完成,然后逐个将屏幕外RT转移到屏幕上的RT。