Alternative title: WinRT support for IDirect3DDevice
I've an application that uses the "Direct3D11CaptureFramePool" class to capture the content of an application window as shown here (link)
I would like to port this example to NET 6.0
How to port WinRT code is described here link
This worked as expected. But it was not possible for the IDirect3DDevice
required by the CreateFreeThreaded method
How can i port this code to NET 6.0
uint hr = CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.NativePointer, out IntPtr pUnknown);
if (hr == 0)
{
device = Marshal.GetObjectForIUnknown(pUnknown) as IDirect3DDevice;
Marshal.Release(pUnknown);
}
There is no FromAbi method for IDrect3DDEvice as described here
Edit:
I have the Interface Type, I have a pointer to a IUnknown object, but i cannot get an instance because the Code to get an object for a IUnknown pointer has changed. There is no Windows.Graphics.DirectX.Direct3D11.IDirect3DDevice.FromAbi(pUnknown)
Edit 2:
I've created a sample repo to reproduce the problem: https://github.com/Amberg/GraphicsCaptureItemNet6Problem
This code works with NET 4.8 but not with NET 6. I belive because the
call Marshal.GetObjectForIUnknown(pUnknown)
should be replaced with
IDirect3DDevice.FromAbi(pUnknown)
but there is no such method
internal class Program
{
[DllImport(
"d3d11.dll",
EntryPoint = "CreateDirect3D11DeviceFromDXGIDevice",
SetLastError = true,
CharSet = CharSet.Unicode,
ExactSpelling = true,
CallingConvention = CallingConvention.StdCall
)]
static extern UInt32 CreateDirect3D11DeviceFromDXGIDevice(IntPtr dxgiDevice, out IntPtr graphicsDevice);
static void Main(string[] args)
{
using var sharpDxDevice = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport);
IDirect3DDevice direct3dDevice = CreateDirect3DDeviceFromSharpDXDevice(sharpDxDevice);
// this will throw internal cast exception
using var framePool = Direct3D11CaptureFramePool.CreateFreeThreaded(
direct3dDevice,
DirectXPixelFormat.B8G8R8A8UIntNormalized,
2,
new SizeInt32(64, 64));
}
private static IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(SharpDX.Direct3D11.Device sharpDxDevice)
{
IDirect3DDevice device = null;
using (var dxgiDevice = sharpDxDevice.QueryInterface<SharpDX.DXGI.Device3>())
{
uint hr = CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.NativePointer, out IntPtr pUnknown);
if (hr == 0)
{
// with NET 6 there should be something like
// IDirect3DDevice.FromAbi(pUnknown)
// see here https://github.com/microsoft/CsWinRT/blob/master/docs/interop.md#create-rcw
device = Marshal.GetObjectForIUnknown(pUnknown) as IDirect3DDevice;
Marshal.Release(pUnknown);
}
}
return device;
}
}
CodePudding user response:
With .NET 6 and CsWinRT, you can write your CreateDirect3DDeviceFromSharpDXDevice
function like this:
private static IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(SharpDX.Direct3D11.Device sharpDxDevice)
{
if (CreateDirect3D11DeviceFromDXGIDevice(sharpDxDevice.NativePointer, out var punk) != 0)
return null;
return WinRT.MarshalInterface<IDirect3DDevice>.FromAbi(punk);
}