How to use Direct3D device manager?

I would like to share one Direct3D device between multiple threads and objects in my Direct3D application. I came across a Direct3D device manager that looks the way I want, although I do not do any video processing or video acceleration: http://msdn.microsoft.com/en-us/library/windows/desktop/aa965267(v= vs. 85) .aspx

In my code, I do the following:

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

My question is: when I created Direct3D device manager, how can I share direct3d device manager with other objects without going around the pointer to device manager? Microsoft specifically stated that it is doing the following, but I do not know what the following really means:

The device owner must provide a way for other objects to obtain a pointer to the IDirect3DDeviceManager9 interface. The standard mechanism is to implement the IMFGetService interface. The service GUID is MR_VIDEO_ACCELERATION_SERVICE.

Can someone show me how to split device manager using IMFGetService interface?

+6
source share
1 answer

If you are not processing the video, I see no reason to implement and / or use the IDirect3DDeviceManager9 interface.

Simply implement your own way to control the lifetime of a Direct3D device by making the interface pointer available for your objects / threads and synchronize. A Direct3D device is not some kind of magical thing that can only be used between objects / streams using IDirect3DDeviceManager9 . This is just like any other resource. And if you initialize it correctly, you can even call certain methods simultaneously from different threads (i.e. almost everything that does not depend on the state of the device, which can be changed by another thread).

The availability of an interface pointer can be as simple as having a single element containing a pointer. Or, if your objects / threads are already collaborating somehow, they already have some ways of exchanging information. Therefore, I assume that you should simply expand on what you already have in order to give objects / threads access to the Direct3D device. And synchronization can be easily done using CRITICAL_SECTION .

If you really want to use IDirect3DDeviceManager9 , then, as I understand it, you should implement the IMFGetService interface for all objects from which you want to access IDirect3DDeviceManager9 . Implement the GetService function GetService that when you query MR_VIDEO_ACCELERATION_SERVICE / IDirect3DDeviceManager9 it MR_VIDEO_ACCELERATION_SERVICE interface pointer to the object that controls your Direct3D device.


EDIT: Regarding the sample code: I hope that the explanation given here is enough. Sharing materials between multiple threads is something I dare not try to explain with a short sample code. If you know how to write multithreaded applications, then using a Direct3D device is no different from how it is done with other resources. And if you don’t know how to write multithreaded applications, then this topic is too complicated for a single answer on stackoverflow.

Regarding the question of why MS recommends using IDirect3DDeviceManager9 ... well, I don't know such a general recommendation. It is simply recommended when processing video (using DXVA, EVR, etc.). Or more like a mandate; I'm not sure if you can share a D3D device, for example. Enhanced Video Renderer without using the D3D device manager. This is what the D3D Device Manager was created for. Sharing a VMR9 device with a visualization tool is possible in only two ways:

Documented way: Only ever access a device from a VMR9 “real” callback. This is quite limiting - for example, you are limited by the frame rate of a video.

Undocumented way: do not call IVMRFilterConfig9::SetNumberOfStreams and only connect one input stream. Thus, VMR9 will not switch to “mixer mode”, and when not in “mixer mode”, VMR9 will not change the state of the device. Therefore, if a D3D device has been initialized with multithreading, you can freely use a D3D device, while VMR9 uses the same device.

Also with VMR9 it was not possible to use the D3D device in another DirectShow filter. The D3D Device Manager improves this by giving filters and your own program code the ability to use a D3D device, including state changes. If, however, you implement each component that will use the D3D device on its own, then there really is no point in controlling the D3D device. And even if you use third-party components that require a D3D device, you can only use the D3D device manager if these components support it. Most likely, this is not the case if these components are not filters / components of DirectShow or MediaFoundation.

+4
source

Source: https://habr.com/ru/post/918705/


All Articles