using System; using System.Runtime.InteropServices; using Windows.Graphics.DirectX.Direct3D11; using WinRT; namespace ytLive.Services; /// /// Bridges a native D3D11 device into the WinRT /// the capture API needs. CsWinRT doesn't project the Direct3D11Helper static, /// so this creates the device with D3D11CreateDevice and converts it via the /// WinRT interop export CreateDirect3D11DeviceFromDXGIDevice (d3d11.dll). /// /// This deliberately does NOT use the older QI-for-IDirect3DDxgiInterfaceAccess /// trick: the raw D3D11 device stopped exposing that interface on newer Windows /// (verified E_NOINTERFACE on build 26200, hardware and WARP alike), while /// CreateDirect3D11DeviceFromDXGIDevice keeps working. One shared device per /// process. /// internal static class Direct3D11Helper { private const uint D3D11CreateDeviceBgraSupport = 0x20; private const uint D3D11SdkVersion = 7; private const int DriverTypeHardware = 1; // IDirect3DDxgiInterfaceAccess (the legacy bridge) is only exposed on an // 11.1 device AND requires the 11.1 runtime to be in the requested set — // with pFeatureLevels = NULL D3D11CreateDevice never creates 11.1, so the // array must be explicit (11.1 first, then descending). private static readonly int[] FeatureLevels = { 0xB100, 0xB000, 0xA100, 0xA000, 0x9300, 0x9200, 0x9100 }; private static IDirect3DDevice? _sharedDevice; private static readonly object Gate = new(); public static IDirect3DDevice CreateDevice() { if (_sharedDevice != null) return _sharedDevice; lock (Gate) { return _sharedDevice ??= CreateDeviceCore(); } } private static IDirect3DDevice CreateDeviceCore() { var hr = D3D11CreateDevice(IntPtr.Zero, DriverTypeHardware, IntPtr.Zero, D3D11CreateDeviceBgraSupport, FeatureLevels, (uint)FeatureLevels.Length, D3D11SdkVersion, out var devicePtr, out _, out var contextPtr); if (hr != 0) throw Marshal.GetExceptionForHR(hr)!; try { var dxgiGuid = new Guid("54EC77FA-1377-44E6-8C32-88FD5F44C84C"); var qiHr = Marshal.QueryInterface(devicePtr, ref dxgiGuid, out var dxgiDevice); if (qiHr != 0) throw Marshal.GetExceptionForHR(qiHr)!; try { hr = CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice, out var winrtDevice); if (hr != 0) throw Marshal.GetExceptionForHR(hr)!; return MarshalInterface.FromAbi(winrtDevice); } finally { Marshal.Release(dxgiDevice); } } finally { Marshal.Release(devicePtr); Marshal.Release(contextPtr); } } [DllImport("d3d11.dll")] private static extern int D3D11CreateDevice(IntPtr pAdapter, int driverType, IntPtr software, uint flags, int[]? featureLevels, uint featureLevelsCount, uint sdkVersion, out IntPtr device, out int featureLevel, out IntPtr immediateContext); [DllImport("d3d11.dll", ExactSpelling = true)] private static extern int CreateDirect3D11DeviceFromDXGIDevice(IntPtr dxgiDevice, out IntPtr graphicsDevice); }