如何在 NET 5 / 6 中使用 Direct3D11CaptureFramePool
How to use Direct3D11CaptureFramePool in NET 5 / 6
替代标题: WinRT 对 IDirect3DDevice 的支持
我有一个应用程序使用“Direct3D11CaptureFramePool" class to capture the content of an application window as shown here (link)
我想将此示例移植到 NET 6.0
此处介绍了如何移植 WinRT 代码 link
这按预期工作。但是 CreateFreeThreaded method
要求的 IDirect3DDevice
是不可能的
如何将此代码移植到 NET 6.0
uint hr = CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.NativePointer, out IntPtr pUnknown);
if (hr == 0)
{
device = Marshal.GetObjectForIUnknown(pUnknown) as IDirect3DDevice;
Marshal.Release(pUnknown);
}
没有描述的 IDrect3DDEvice 的 FromAbi 方法here
编辑:
我有接口类型,我有一个指向 IUnknown object 的指针,但我无法获取实例,因为获取 IUnknown 指针的 object 的代码已更改。没有 Windows.Graphics.DirectX.Direct3D11.IDirect3DDevice.FromAbi(pUnknown)
编辑 2:
我创建了一个示例存储库来重现该问题:
https://github.com/Amberg/GraphicsCaptureItemNet6Problem
此代码适用于 NET 4.8 但不适用于 NET 6。我相信是因为
call Marshal.GetObjectForIUnknown(pUnknown)
应替换为
IDirect3DDevice.FromAbi(pUnknown)
但是没有这样的方法
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;
}
}
使用 .NET 6 和 CsWinRT,您可以像这样编写 CreateDirect3DDeviceFromSharpDXDevice
函数:
private static IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(SharpDX.Direct3D11.Device sharpDxDevice)
{
if (CreateDirect3D11DeviceFromDXGIDevice(sharpDxDevice.NativePointer, out var punk) != 0)
return null;
return WinRT.MarshalInterface<IDirect3DDevice>.FromAbi(punk);
}
替代标题: WinRT 对 IDirect3DDevice 的支持
我有一个应用程序使用“Direct3D11CaptureFramePool" class to capture the content of an application window as shown here (link)
我想将此示例移植到 NET 6.0
此处介绍了如何移植 WinRT 代码 link 这按预期工作。但是 CreateFreeThreaded method
要求的IDirect3DDevice
是不可能的
如何将此代码移植到 NET 6.0
uint hr = CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.NativePointer, out IntPtr pUnknown);
if (hr == 0)
{
device = Marshal.GetObjectForIUnknown(pUnknown) as IDirect3DDevice;
Marshal.Release(pUnknown);
}
没有描述的 IDrect3DDEvice 的 FromAbi 方法here
编辑:
我有接口类型,我有一个指向 IUnknown object 的指针,但我无法获取实例,因为获取 IUnknown 指针的 object 的代码已更改。没有 Windows.Graphics.DirectX.Direct3D11.IDirect3DDevice.FromAbi(pUnknown)
编辑 2:
我创建了一个示例存储库来重现该问题: https://github.com/Amberg/GraphicsCaptureItemNet6Problem
此代码适用于 NET 4.8 但不适用于 NET 6。我相信是因为
call Marshal.GetObjectForIUnknown(pUnknown)
应替换为
IDirect3DDevice.FromAbi(pUnknown)
但是没有这样的方法
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;
}
}
使用 .NET 6 和 CsWinRT,您可以像这样编写 CreateDirect3DDeviceFromSharpDXDevice
函数:
private static IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(SharpDX.Direct3D11.Device sharpDxDevice)
{
if (CreateDirect3D11DeviceFromDXGIDevice(sharpDxDevice.NativePointer, out var punk) != 0)
return null;
return WinRT.MarshalInterface<IDirect3DDevice>.FromAbi(punk);
}