2012-06-21 21 views
6

Me gustaría compartir un dispositivo Direct3D entre múltiples hilos y objetos en mi aplicación Direct3D. Me encontré con el administrador de dispositivos de Direct3D, que se parece a lo que yo quiero, aunque no estoy haciendo ningún tipo de procesamiento de vídeo o vídeo de aceleración: http://msdn.microsoft.com/en-us/library/windows/desktop/aa965267(v=vs.85).aspx¿Cómo uso el Administrador de dispositivos Direct3D?

En mi código, yo estoy haciendo lo siguiente:

// 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(); 

Mi pregunta es una vez que he creado el administrador de dispositivos Direct3D, ¿cómo comparto el administrador de dispositivos direct3d con otros objetos sin pasar un puntero al administrador de dispositivos? Microsoft ha dicho específicamente a hacer lo siguiente, pero no tengo ni idea de lo que realmente significa lo siguiente:

El propietario del dispositivo debe proporcionar un camino para otros objetos para obtener un puntero a la interfaz IDirect3DDeviceManager9. El mecanismo estándar es para implementar la interfaz IMFGetService. El GUID del servicio es MR_VIDEO_ACCELERATION_SERVICE.

¿Alguien me puede mostrar cómo compartir el administrador de dispositivos utilizando la interfaz IMFGetService?

Respuesta

4

Si no está haciendo ningún procesamiento de video, no veo sentido en la implementación y/o uso de la interfaz IDirect3DDeviceManager9.

Simplemente implemente su propia forma de administrar la vida útil del dispositivo Direct3D, haciendo que el puntero de la interfaz esté disponible para sus objetos/hilos y realice la sincronización. Un dispositivo Direct3D no es ningún tipo de cosa mágica que solo se puede compartir entre objetos/hilos por medio de un IDirect3DDeviceManager9. Es como cualquier otro recurso. Y si lo inicializa correctamente, incluso puede invocar ciertos métodos al mismo tiempo desde diferentes hilos (es decir, prácticamente todo lo que no dependa de un estado del dispositivo que pueda ser modificado por otro hilo).

Hacer que el puntero de interfaz esté disponible puede ser tan simple como tener un singleton que contenga el puntero. O bien, si sus objetos/hilos ya colaboran de alguna forma, ya deben tener algún medio de intercambio de información. Así que supongo que debería poder ampliar lo que ya tiene para dar acceso a los objetos/subprocesos al dispositivo Direct3D. Y la sincronización se puede hacer fácilmente usando un CRITICAL_SECTION.

Si realmente desea utilizar IDirect3DDeviceManager9, a continuación, - por lo que yo entiendo - que tiene que implementar la interfaz IMFGetService en todos los objetos de los que desea obtener acceso a la IDirect3DDeviceManager9. Implemente la función GetService para que cuando se le solicite MR_VIDEO_ACCELERATION_SERVICE/IDirect3DDeviceManager9, devuelva un puntero de interfaz al objeto que gestiona su dispositivo Direct3D.


EDIT: En cuanto al código de ejemplo: espero que la explicación dada aquí es suficiente. Compartir cosas entre múltiples hilos es algo que no me atrevo a explicar con una breve muestra de código. Si sabe cómo escribir aplicaciones de subprocesos múltiples, entonces el uso de un dispositivo Direct3D no es diferente de cómo se hace con otros recursos. Y si no sabe cómo escribir aplicaciones de subprocesos múltiples, ese tema es demasiado complejo para una sola respuesta de stackoverflow.

En cuanto a la pregunta de por qué MS recomienda utilizar IDirect3DDeviceManager9 ... bueno, no conozco una recomendación tan general.Se recomienda cuando se procesa video (usando DXVA, EVR, etc.). O más como mandato; No estoy seguro de si puedes compartir el dispositivo D3D, p. el Representador de video mejorado sin usar el administrador de dispositivos D3D. Para eso se creó el administrador de dispositivos D3D, después de todo. Con el VMR9 compartir un dispositivo con el renderizador solo fue posible de dos maneras:

La forma documentada: solo tiene acceso al dispositivo desde la "actual" devolución de llamada del VMR9. Lo cual es bastante limitante, p. está limitado a la velocidad de fotogramas del video.

El modo no documentado: NO llame al IVMRFilterConfig9::SetNumberOfStreams y solo conecte un flujo de entrada. De esta forma, VMR9 no cambiará al "modo de mezclador" y, cuando no se encuentre en el "modo de mezclador", VMR9 no cambiará ningún estado del dispositivo. Entonces, si el dispositivo D3D se inicializó en subprocesos múltiples, entonces puede usar el dispositivo D3D libremente mientras VMR9 está usando el mismo dispositivo.

También con el VMR9 no fue posible usar el dispositivo D3D en otro filtro DirectShow. El administrador de dispositivos D3D mejora eso, dando a los filtros y a su propio código de aplicación la capacidad de usar el dispositivo D3D, incluidos los estados cambiantes. Sin embargo, si implementa cada componente que usará el dispositivo D3D usted mismo, entonces no tiene ningún sentido utilizar el administrador de dispositivos D3D. E incluso si está utilizando componentes de terceros que requieren un dispositivo D3D, solo podrá usar el administrador de dispositivos D3D si dichos componentes lo admiten. Lo cual probablemente no será el caso a menos que esos componentes sean filtros/componentes DirectShow o MediaFoundation.

Cuestiones relacionadas