2012-06-21 13 views
6

Mi piacerebbe condividere un dispositivo Direct3D tra più thread e oggetti nella mia applicazione Direct3D. Mi sono imbattuto in Gestione periferiche Direct3D, che assomiglia a quello che voglio, anche se io non sto facendo alcuna elaborazione di video o un video accelerazione: http://msdn.microsoft.com/en-us/library/windows/desktop/aa965267(v=vs.85).aspxCome si utilizza Direct3D Device Manager?

Nel mio codice, sto facendo la seguente:

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

La mia domanda è una volta che ho creato il gestore dispositivi Direct3D, come faccio a condividere il gestore dispositivi direct3d con altri oggetti senza passare attorno a un puntatore al gestore dispositivi? Microsoft ha espressamente detto di fare quanto segue, ma non ho idea di cosa si intende veramente dal seguente:

Il proprietario del dispositivo deve fornire un modo per altri oggetti per ottenere un puntatore all'interfaccia IDirect3DDeviceManager9. Il meccanismo standard è quello di implementare l'interfaccia IMFGetService. Il GUID di servizio è MR_VIDEO_ACCELERATION_SERVICE.

Qualcuno può mostrarmi come condividere il gestore dispositivi utilizzando l'interfaccia IMFGetService?

risposta

4

Se non si sta eseguendo alcuna elaborazione video, non vedo l'utilità di implementare e/o utilizzare l'interfaccia IDirect3DDeviceManager9.

Basta implementare il proprio modo di gestire la durata del dispositivo Direct3D, rendendo il puntatore dell'interfaccia disponibile per gli oggetti/thread e per eseguire la sincronizzazione. Un dispositivo Direct3D non è un tipo di cosa magica che può essere condivisa solo tra oggetti/thread per mezzo di un IDirect3DDeviceManager9. È proprio come qualsiasi altra risorsa. E se lo si inizializza correttamente, è anche possibile chiamare determinati metodi contemporaneamente da diversi thread (vale a dire praticamente tutto ciò che non si basa su uno stato del dispositivo che potrebbe essere modificato da un altro thread).

Rendere disponibile il puntatore dell'interfaccia può essere semplice come avere un singleton che contiene il puntatore. Oppure, se i tuoi oggetti/thread già collaborano in qualche modo, devono già avere qualche mezzo per scambiare informazioni. Quindi suppongo che dovresti essere in grado di estendere solo quello che hai già a dare l'accesso agli oggetti/thread al dispositivo Direct3D. E la sincronizzazione può essere fatta facilmente usando un CRITICAL_SECTION.

Se davvero si vuole utilizzare IDirect3DDeviceManager9, quindi - per quanto mi risulta - è necessario implementare l'interfaccia IMFGetService su tutti gli oggetti da cui si desidera ottenere l'accesso al IDirect3DDeviceManager9. Implementare la funzione GetService in modo che quando viene richiesto MR_VIDEO_ACCELERATION_SERVICE/IDirect3DDeviceManager9, restituisce un puntatore all'interfaccia che gestisce il dispositivo Direct3D.


EDIT: Per quanto riguarda il codice di campione: spero che la spiegazione data qui è sufficiente. Condividere cose tra più thread è qualcosa che non oso provare a spiegare con un breve esempio di codice. Se sai come scrivere applicazioni multi-thread, quindi utilizzare un dispositivo Direct3D non è diverso da come è fatto con altre risorse. E se non sai come scrivere applicazioni multi-thread, l'argomento è troppo complesso per una singola risposta StackOverflow.

Per quanto riguarda la domanda sul perché MS raccomanda di utilizzare IDirect3DDeviceManager9 ... beh, non sono a conoscenza di una raccomandazione di questo tipo.È consigliato solo quando si esegue l'elaborazione video (utilizzando DXVA, EVR ecc.). O più come mandato; Non sono sicuro che tu possa condividere il dispositivo D3D con ad es. il renderizzatore video avanzato senza utilizzare il gestore dispositivi D3D. Questo è il motivo per cui è stato creato il D3D Device Manager. Con VMR9 la condivisione di un dispositivo con il renderer era possibile solo in due modi:

Il modo documentato: accedere sempre il dispositivo solo dal callback "presente" del VMR9. Il che è piuttosto limitante, ad es. sei limitato alla frequenza fotogrammi del video.

Il modo non documentato: NON chiamare IVMRFilterConfig9::SetNumberOfStreams e collegare solo un flusso di input. In questo modo VMR9 non passerà alla "modalità mixer" e quando non è in "modalità mixer" VMR9 non cambierà nessuno stato del dispositivo. Quindi, se il dispositivo D3D è stato inizializzato con multithreading, è possibile utilizzare liberamente il dispositivo D3D mentre VMR9 sta utilizzando lo stesso dispositivo.

Inoltre con VMR9 non è stato possibile utilizzare il dispositivo D3D in un altro filtro DirectShow. Il dispositivo di gestione D3D migliora, fornendo ai filtri e al codice dell'applicazione la possibilità di utilizzare il dispositivo D3D, compresi gli stati di modifica. Se però implementi tutti i componenti che useranno il dispositivo D3D da solo, allora non c'è davvero alcun punto in usind il device manager D3D. E anche se utilizzi componenti di terze parti che richiedono un dispositivo D3D, sarai in grado di utilizzare il gestore dispositivi D3D solo se tali componenti lo supportano. Quale probabilmente non sarà il caso a meno che quei componenti capita di essere DirectShow o MediaFoundation filtri/componenti.