2012-06-21 19 views
6

Ich möchte ein Direct3D-Gerät zwischen mehreren Threads und Objekten in meiner Direct3D-Anwendung teilen. Ich kam in der Direct3D-Geräte-Manager, das wie folgt aussieht, was ich will, obwohl ich keine Videoverarbeitung oder Videobeschleunigung so mache: http://msdn.microsoft.com/en-us/library/windows/desktop/aa965267(v=vs.85).aspxWie benutze ich den Direct3D Device Manager?

In meinem Code, ich tue das folgende:

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

Meine Frage ist, sobald ich den Direct3D-Gerätemanager erstellt habe, wie teile ich den direct3d-Gerätemanager mit anderen Objekten, ohne einen Zeiger auf den Gerätemanager zu übergeben? Microsoft hat ausdrücklich gesagt, die folgenden zu tun, aber ich habe keine Ahnung, was wirklich durch die folgenden gemeint ist:

Der Gerätebesitzer bietet eine Möglichkeit, muß für andere Objekte einen Zeiger auf die IDirect3DDeviceManager9 Schnittstelle zu erhalten. Der Standardmechanismus ist implementieren die IMFGetService-Schnittstelle. Die Service-GUID ist MR_VIDEO_ACCELERATION_SERVICE.

Kann mir jemand zeigen, wie man den Gerätemanager mithilfe der IMFGetService-Schnittstelle teilt?

Antwort

4

Wenn Sie keine Videoverarbeitung machen, dann sehe ich keinen Sinn in der Implementierung und/oder Verwendung der IDirect3DDeviceManager9 Schnittstelle.

Implementieren Sie einfach Ihre eigene Methode, die Lebensdauer des Direct3D-Geräts zu verwalten, indem Sie den Schnittstellenzeiger für Ihre Objekte/Threads verfügbar machen und die Synchronisation durchführen. Ein Direct3D-Gerät ist keine magische Sache, die nur mit Hilfe einer IDirect3DDeviceManager9 zwischen Objekten/Threads geteilt werden kann. Es ist wie jede andere Ressource. Und wenn Sie es richtig initialisieren, können Sie sogar bestimmte Methoden gleichzeitig aus verschiedenen Threads aufrufen (d. H. So ziemlich alles, was nicht auf einem Gerätezustand beruht, der von einem anderen Thread geändert werden könnte).

Die Bereitstellung des Schnittstellenzeigers kann so einfach sein wie ein Singleton, der den Zeiger enthält. Oder, wenn Ihre Objekte/Threads bereits in irgendeiner Weise zusammenarbeiten, müssen sie bereits einige Mittel zum Austausch von Informationen haben. Ich nehme an, Sie sollten in der Lage sein, einfach das zu erweitern, was Sie bereits haben, um den Objekten/Threads Zugriff auf das Direct3D-Gerät zu geben. Und die Synchronisierung kann einfach mit einem CRITICAL_SECTION durchgeführt werden.

Wenn Sie wirklich wollen, IDirect3DDeviceManager9 verwenden, dann - soweit ich es verstehe - Sie haben die IMFGetService Schnittstelle für alle Objekte, aus denen Sie Zugang zu bekommen, um die IDirect3DDeviceManager9 wollen implementieren. Implementieren Sie die GetService-Funktion so, dass bei der Abfrage MR_VIDEO_ACCELERATION_SERVICE/IDirect3DDeviceManager9 ein Schnittstellenzeiger auf das Objekt zurückgegeben wird, das Ihr Direct3D-Gerät verwaltet.


EDIT: In Bezug auf dem Code-Beispiel: Ich hoffe, dass die hier gegebene Erklärung genug. Das Teilen von Inhalten zwischen mehreren Threads ist etwas, was ich nicht versuchen möchte, es mit einem kurzen Codebeispiel zu erklären. Wenn Sie wissen, wie Sie Multithread-Anwendungen schreiben, unterscheidet sich die Verwendung eines Direct3D-Geräts nicht von der bei anderen Ressourcen. Und wenn Sie nicht wissen, wie man Multithread-Anwendungen schreibt, ist dieses Thema für eine einzelne Stackoverflow-Antwort bei weitem zu komplex.

In Bezug auf die Frage, warum MS empfiehlt IDirect3DDeviceManager9 ... gut zu verwenden, ist mir eine solche allgemeine Empfehlung nicht bekannt.Es wird nur empfohlen, wenn Sie eine Videoverarbeitung durchführen (mit DXVA, EVR usw.). Oder mehr wie vorgeschrieben; Ich bin mir nicht sicher, ob Sie das D3D-Gerät mit z. den Enhanced Video Renderer, ohne den D3D-Gerätemanager zu verwenden. Dafür wurde der D3D-Gerätemanager geschaffen. Mit dem VMR9 war die gemeinsame Nutzung eines Geräts mit dem Renderer nur auf zwei Arten möglich:

Der dokumentierte Weg: greifen immer nur vom "vorhandenen" Callback des VMR9 auf das Gerät zu. Was eher einschränkend ist - z.B. Sie sind auf die Bildrate des Videos beschränkt.

Der undokumentierte Weg: rufen Sie nicht IVMRFilterConfig9::SetNumberOfStreams und nur einen Eingabestrom verbinden. Auf diese Weise wird VMR9 nicht in den "Mixer-Modus" wechseln, und wenn nicht im "Mixer-Modus", wird VMR9 keine Gerätezustände ändern. Wenn also das D3D-Gerät Multithreading initialisiert wurde, können Sie das D3D-Gerät frei verwenden, während VMR9 dasselbe Gerät verwendet.

Auch mit dem VMR9 war es nicht möglich, das D3D-Gerät in einem anderen DirectShow-Filter zu verwenden. Der D3D-Gerätemanager verbessert dies und gibt Filtern und Ihrem eigenen Anwendungscode die Möglichkeit, das D3D-Gerät zu verwenden - einschließlich der Änderung von Zuständen. Wenn Sie jedoch jede Komponente implementieren, die das D3D-Gerät selbst verwendet, dann hat der D3D-Gerätemanager keinen Sinn. Und selbst wenn Sie Komponenten von Drittanbietern verwenden, für die ein D3D-Gerät erforderlich ist, können Sie den D3D-Gerätemanager nur verwenden, wenn diese Komponenten dies unterstützen. Dies wird wahrscheinlich nicht der Fall sein, es sei denn, diese Komponenten sind DirectShow- oder MediaFoundation-Filter/Komponenten.