What are the best multithreading methods with Direct2D and DXGI (D3D interop)?

Ideally, I would like several workflows to be able to display objects off-screen, and then โ€œtransferโ€ the displayed content to the on-screen target. With hwnd rendering objects this doesn't seem to be a problem (msdn has an example).

I'm not quite sure how to do this when the purpose of rendering on the screen is based on the DXGI swap chain. As far as I know, I can only have one swap chain per window. Therefore, I can have only one rendering target based on the swap chain. This means that on-screen rendering can only be done through this single rendering goal.

If my assumptions above are true, what is the best way to handle multi-threaded rendering? Do I need to serialize access to a screen target? Should worker threads share a single multi-threaded d2d factory? Can the BeginDraw / EndDraw / Present desktop be executed on the screen on workflows (i.e. Streams that do not create a landing page on the screen) if there is an appropriate locking mechanism?

I would be grateful for any suggestions. Thanks.

+4
source share
2 answers

I am solving the same problem right now! According to my reading on MSDN, the best way is:

  • Using a multi-threaded factory - allows you to share resources (see also the link with a quote below).
  • Be careful with some deadlock situations (details below).
  • You will probably have to use ID2D1MultiThread to lock when drawing using Direct3D.

I do not yet have a reliable working multi-threaded set of Direct2D functions, even after that, so thatโ€™s all I know so far - I donโ€™t yet know about the other caveats, etc. that necessarily exist.

Some useful key bits:

You can create a multi-threaded instance of Direct2D factory. You can use and share a multi-threaded factory and all its resources from more than one stream, but access to these resources (via Direct2D calls) is serialized by Direct2D, so there are no access conflicts. If your application calls only the Direct2D API, this protection is automatically performed by Direct2D at a granular level with minimal overhead.

ID2D1Factory* m_D2DFactory; // Create a Direct2D factory. HRESULT hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_MULTI_THREADED, &m_D2DFactory ); 

There is also this very important warning:

Multi-user considerations

When you use DXGI in an application with multiple threads, you need to be careful to avoid creating a deadlock where two different threads are waiting for each other to complete. There are two situations where this can happen.

  • The rendering stream rather than the pump message stream.
  • The thread executing the DXGI API is not the same thread that created the window.

Be careful that never when the thread of the message-pump appears on the render thread, full-screen swap chains. For example, a call to IDXGISwapChain1 :: Present1 (from the rendering stream) may cause the stream to be visualized to wait on the pump message stream. When changing the mode, this scenario is possible if calls to Present1 :: SetWindowPos () or :: SetWindowStyle (), and any of these methods call :: Send message (). In this case, if the message-pump flow has a critical section protecting it, or if the rendering flow is blocked, then the two flows will be inhibited.

+4
source

For off-screen rendering purposes, you can create separate D2DFactories and attach them to the corresponding rendering targets created using CreateWicBitmapRenderTarget or CreateDxgiSurfaceRenderTarget. When transferring it to a screen target, you will have to wait until all streams are finished, and then transfer each external RT screen to the RT screen one by one.

+1
source

All Articles