3
\$\begingroup\$

I have an image in my WPF application that uses a D3DImage to render DirectX content. On the DirectX side I render everything to a Texture2D using SharpDX (a C# DirectX wrapper), but I'm not sure how to convert the rendered texture to a D3DImage.

I found the D3DImage.SetBackBuffer(D3DResourceType backBufferType, IntPtr backBuffer) method, but that requires the texture to be a DXGI Surface. Here's the code I'm working with:

// renderTexture is a Texture2D that serves as the renderTarget for the DirectX content
// d3dimg is the D3DImage that WPF uses

d3dimg.Lock()
d3dimg.SetBackBuffer(D3DResourceType.IDirect3DSurface9, 
                     renderTexture.QueryInterface<Surface>().NativePointer);
d3dimg.Unlock();

But for some reason, the SetBackBuffer function call throws an exception saying that the "specified cast is not valid," even though I'm not doing any casts here (as far as I can see). What am I doing wrong?

\$\endgroup\$
1
\$\begingroup\$

Did you solve this? D3DImage only works with Direct3D 9Ex surface so it won't work with DXGI/Texture2D which are Direct3D 11... unless you arrange some very tricky DXGI surface sharing between 11 -> 9Ex in advance. I have all the numerous code fragments that prove this should be possible (i.e. accelerated Direct3D 11 video pipeline targeting WPF) but have struggled to fully stitch them together after months of work (albeit starting from zero Direcr3D knowledge). Note that this form of surface sharing requires coordinating synchronization manually. In comparison, If you can switch to Direct3D 9 source everything works very easily.

The casting error you are getting is from inside the D3DImage, when it fails to cast your 11 surface to the Surface9Ex it expects and requires.


[edit: see my comment below for more information on a full solution]

\$\endgroup\$
  • 1
    \$\begingroup\$ If anyone is interested, I did eventually get a DXGI/Direct3D11 video pipeline targeting WPF in .NET 4.7 working in Windows Media Foundation MediaSession mode. This requires writing a custom IMFMediaSink that shunts to an integrated D3DImage. At first (by specifying MF_SA_D3D11_SHARED_WITHOUT_MUTEX), I was able to directly share each DXGI surface into D3D9 by calling D3DImage.SetBackBuffer() once per frame, but later moved to a manual D3D11 CopyResource into my own ID3D11Texture2D1 because it allows for the less-thrashy use of D3DImage.AddDirtyRect() instead. \$\endgroup\$ – Glenn Slayden Nov 12 '17 at 4:25
  • \$\begingroup\$ Forgot to mention, the code is 100% C#. As some will know, a huge part of the challenge with Windows Media Foundation is getting its endless infinitude of COM interfaces (IMFMediaSink for starters, in this case) on semi-free-threaded COM instances--including assorted asynchronous callbacks--working property in pure managed code. Same goes for DXGI and Direct3D11, for which there are managed interop libraries out there, but in this case I ended up just rolling my own so that I could design the p/Invoke marshaling around the exact needs of this scenario. \$\endgroup\$ – Glenn Slayden Nov 12 '17 at 4:38
  • \$\begingroup\$ One more detail that might help people working in this space: A big problem you confront in replacing the EVR model, which is what is required here, is that it initially appears that you then take on the responsibility of handling uncompressed video and de-interlacing it, etc., tasks which were not your burden in the old D3D9 "custom presenter." A breakthrough here was the obscure Media Foundation attribute MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK. When asserted on your IMFTopology, a conversion MFT is added to the pipeline to handle the conversions, which hugely simplifies your IMFMediaSink. \$\endgroup\$ – Glenn Slayden Nov 12 '17 at 4:54
  • \$\begingroup\$ Is the code available somewhere? \$\endgroup\$ – DanielB May 7 at 6:47
  • \$\begingroup\$ @DanielB Unfortunately not quite yet. But I consider the managed WPF app very stable and successful and actually use it exclusively--and heavily--as my own favorite full-time media player. I'm happy to discuss the details more, but you should realize that even in C# (or perhaps because of it--there's a certain weird productivity trade-off here)--it's a complex task overall. Please create an attached chat discussion for this question if you wish to discuss further. \$\endgroup\$ – Glenn Slayden May 7 at 7:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.