Каковы лучшие практики для многопоточности с Direct2D и DXGI (взаимодействие D3D)? - PullRequest
4 голосов
/ 05 июня 2011

В идеале я хотел бы иметь несколько рабочих потоков, чтобы иметь возможность выполнять рендеринг за пределами экранных целей рендеринга, а затем «передавать» визуализированный контент на экранную цель. С целями рендеринга hwnd это, по-видимому, не проблема (например, у msdn).

Я не совсем уверен, как это сделать, если цель рендеринга на экране основана на цепочке свопов DXGI. Насколько я знаю, у меня может быть только одна цепочка подкачки на окно. Поэтому у меня может быть только одна цель рендера, основанная на цепочке обмена. Это означает, что визуализация на экране может быть выполнена только через эту единственную цель рендеринга.

Если мои вышеприведенные предположения верны, каков наилучший способ обработки многопоточного рендеринга? Нужно ли сериализовать доступ к экранной цели? Должны ли рабочие потоки использовать одну многопоточную фабрику d2d? Может ли BeginDraw / EndDraw / Present экранной цели выполняться в рабочих потоках (то есть потоках, которые не создавали экранную цель), если установлен надлежащий механизм блокировки?

Буду признателен за любые предложения. Спасибо.

Ответы [ 2 ]

4 голосов
/ 25 января 2014

Я решаю эту проблему прямо сейчас!Согласно моим прочтениям в MSDN, лучший способ:

У меня естьеще не получил надежно работающего многопоточного набора функций Direct2D, даже после этого, так что это все, что я знаю до сих пор - я еще не знаю о других предостережениях и т. д., которые обязательно существуют.

Некоторые полезные биты ключей:

Вы можете создать многопоточный экземпляр фабрики Direct2D.Вы можете использовать и совместно использовать многопоточную фабрику и все ее ресурсы из более чем одного потока, но доступ к этим ресурсам (через вызовы Direct2D) сериализуется Direct2D, поэтому не возникает конфликтов доступа.Если ваше приложение вызывает только API-интерфейсы Direct2D, такая защита автоматически выполняется 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 ().В этом случае, если у потока рассылки сообщений есть критическая секция, защищающая его, или если поток рендеринга заблокирован, то эти два потока будут взаимоблокированы.

1 голос
/ 14 июня 2011

Для целей закадрового рендеринга вы можете создать отдельные объекты D2DFactories и прикрепить их к соответствующим закадровым целям рендеринга, созданным с помощью CreateWicBitmapRenderTarget или CreateDxgiSurfaceRenderTarget.Передавая его на экранную цель, вам нужно будет дождаться завершения всех потоков, а затем перенести каждую внеэкранную RT на экранную RT по одному.

...