Alternative title: WinRT support for IDirect3DDevice

我有一个应用程序,它使用"Direct3D11CaptureFramePool"类来捕获应用程序窗口的内容,如下所示(link)

我想把这个例子移植到Net6.0

这里介绍了如何移植WinRT代码

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);
    }

IDrect3DDEvice没有FromAbi方法,如here所述

Edit:

我有接口类型,我有一个指向IUnknown对象的指针,但我无法获取实例,因为为IUnknown指针获取对象的代码已更改.没有 Windows.Graphics.DirectX.Direct3D11.IDirect3DDevice.FromAbi(pUnknown)

Edit 2:

我创建了一个回购示例来重现这个问题:

这段代码适用于Net4.8,但不适用于Net6.我相信,因为

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);
}

.net相关问答推荐

从 Contentful 中的富文本元素中获取价值?

将 Span 传递到函数时出现 F# 错误

查找 2 个已知值之间的字符串

xunit Assert.ThrowsAsync() 不能正常工作?

为什么不能使用 null 作为 Dictionary 的键?

string.Format 如何处理空值?

有什么方法可以使用 .NET 应用程序使用 git 吗?

如何右对齐 DataGridView 列中的文本?

调用委托与方法的性能

如何正确停止BackgroundWorker

日期时间是什么意思?在 C# 中是什么意思?

修剪数组中的所有字符串

为什么使用 ImmutableList 而不是 ReadOnlyCollection?

Environment.GetFolderPath(...CommonApplicationData) 在 Vista 上仍然返回C:\Documents and Settings\

如何知道 DateTime 是否在 C# 中的 DateRange 之间

将 SignalR 2.0 .NET 客户端重新连接到服务器集线器的最佳实践

带有嵌套控件的设计模式

如何隐藏 WPF ListView 的标题?

如何在我的机器上找到 fuslogvw.exe?

判断数据表中是否包含空值的最佳方法