4

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

当屏幕渲染目标基于 DXGI 交换链时,我不太确定该怎么做。据我所知,每个窗口只能有一个交换链。因此,我只能有一个基于交换链的渲染目标。这意味着屏幕上的渲染只能通过那个单一的渲染目标来完成。

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

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

4

2 回答 2

4

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

  • 使用多线程工厂 -这可以让您共享资源(另请参阅下面引用的链接)。
  • 小心一些死锁情况(详情如下。)
  • 在使用 Direct3D 绘图时,您可能需要使用ID2D1MultiThread来锁定。

我还没有一个可靠工作的多线程 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() 并且这些方法中的任何一个调用 ::SendMessage(),则这种情况是可能的。在这种情况下,如果消息泵线程有一个临界区保护它,或者如果渲染线程被阻塞,那么这两个线程将死锁。

于 2014-01-24T22:32:50.467 回答
1

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

于 2011-06-14T08:27:28.743 回答