Как использовать Диспетчер устройств Direct3D?

Я хочу использовать одно устройство Direct3D совместно с несколькими потоками и объектами в своем приложении Direct3D. Я наткнулся на диспетчер устройств Direct3D, который выглядит так, как мне нужно, хотя я не выполняю никакой обработки или ускорения видео: http://msdn.microsoft.com/en-us/library/windows/desktop/aa965267(v=vs.85).aspx

В моем коде я делаю следующее:

  // Create the device manager
  UINT resetToken = 0;
  IDirect3DDeviceManager9* deviceManager = NULL;
  if (FAILED(DXVA2CreateDirect3DDeviceManager9(&resetToken, &deviceManager)))
    return false;

  // Add the device to the device manager
  if (FAILED(deviceManager->ResetDevice(device, resetToken)))
    return false;

  deviceManager->AddRef();

Мой вопрос: после того, как я создал диспетчер устройств Direct3D, как мне поделиться диспетчером устройств Direct3D с другими объектами, не передавая указатель на диспетчер устройств? Microsoft специально сказала сделать следующее, но я понятия не имею, что на самом деле подразумевается под этим:

Владелец устройства должен предоставить другим объектам способ получить указатель на интерфейс IDirect3DDeviceManager9. Стандартный механизм заключается в реализации интерфейса IMFGetService. GUID службы — MR_VIDEO_ACCELERATION_SERVICE.

Может ли кто-нибудь показать мне, как поделиться диспетчером устройств с помощью интерфейса IMFGetService?


person Christian    schedule 21.06.2012    source источник


Ответы (1)


Если вы не занимаетесь никакой обработкой видео, то я не вижу смысла в реализации и/или использовании интерфейса IDirect3DDeviceManager9.

Просто реализуйте свой собственный способ управления временем жизни устройства Direct3D, сделав указатель интерфейса доступным для ваших объектов/потоков и выполняя синхронизацию. Устройство Direct3D — это не какая-то волшебная вещь, которую можно использовать между объектами/потоками только с помощью файла IDirect3DDeviceManager9. Это точно так же, как и любой другой ресурс. И если вы правильно инициализируете его, вы даже можете одновременно вызывать определенные методы из разных потоков (то есть почти все, что не зависит от состояния устройства, которое может быть изменено другим потоком).

Сделать указатель интерфейса доступным можно так же просто, как создать синглтон, который содержит указатель. Или, если ваши объекты/потоки уже каким-то образом сотрудничают, у них уже должны быть какие-то средства обмена информацией. Поэтому я полагаю, что вы должны иметь возможность просто расширить то, что у вас уже есть, чтобы предоставить объектам/потокам доступ к устройству Direct3D. И синхронизацию можно легко выполнить с помощью файла CRITICAL_SECTION.

Если вы действительно хотите использовать IDirect3DDeviceManager9, то, насколько я понимаю, вы должны реализовать интерфейс IMFGetService на всех объектах, из которых вы хотите получить доступ к IDirect3DDeviceManager9. Реализуйте функцию GetService, чтобы при запросе MR_VIDEO_ACCELERATION_SERVICE/IDirect3DDeviceManager9 она возвращала указатель интерфейса на объект, который управляет вашим устройством Direct3D.


EDIT: Что касается примера кода: я надеюсь, что приведенного здесь объяснения достаточно. Совместное использование данных между несколькими потоками — это то, что я не осмеливаюсь объяснить с помощью короткого примера кода. Если вы знаете, как писать многопоточные приложения, то использование устройства Direct3D ничем не отличается от того, как это делается с другими ресурсами. И если вы не знаете, как писать многопоточные приложения, то эта тема слишком сложна для одного ответа на stackoverflow.

По поводу вопроса, почему MS рекомендует использовать IDirect3DDeviceManager9... ну, я не в курсе такой общей рекомендации. Это просто рекомендуется при обработке видео (используя DXVA, EVR и т.д.). Или больше похоже на мандат; Я не уверен, что вы можете поделиться устройством D3D, например. Enhanced Video Renderer без использования диспетчера устройств D3D. В конце концов, именно для этого и был создан диспетчер устройств D3D. С VMR9 совместное использование устройства с рендерером было возможно только двумя способами:

Задокументированный способ: доступ к устройству возможен только из "настоящего" обратного вызова VMR9. Что довольно ограничивает - например. вы ограничены частотой кадров видео.

Недокументированный способ: НЕ вызывайте IVMRFilterConfig9::SetNumberOfStreams и подключайте только один входной поток. Таким образом, VMR9 не переключится в «режим микшера», а когда он не находится в «режиме микшера», VMR9 не изменит никаких состояний устройства. Таким образом, если устройство D3D было инициализировано многопоточным, вы можете свободно использовать устройство D3D, в то время как VMR9 использует то же устройство.

Также с VMR9 вообще невозможно было использовать устройство D3D в другом фильтре DirectShow. Диспетчер устройств D3D улучшает это, предоставляя фильтрам и вашему собственному коду приложения возможность использовать устройство D3D, включая изменение состояний. Однако если вы реализуете каждый компонент, который будет использовать D3D-устройство самостоятельно, тогда нет никакого смысла использовать диспетчер D3D-устройств. И даже если вы используете сторонние компоненты, для которых требуется устройство D3D, вы сможете использовать диспетчер устройств D3D только в том случае, если эти компоненты его поддерживают. Что, вероятно, не будет иметь место, если эти компоненты не будут фильтрами/компонентами DirectShow или MediaFoundation.

person Paul Groke    schedule 23.10.2012