using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace VdiDiagnostics { public class AdapterResult { public string Name; public uint VendorId; public int DeviceResult; } // Enumerate the actual DXGI adapters and create a D3D11 device on each NVIDIA // adapter. A WMI/PnP model name alone does not prove that D3D is operational. public static class D3DProbe { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct AdapterDesc { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string Description; public uint VendorId, DeviceId, SubSysId, Revision; public UIntPtr DedicatedVideoMemory, DedicatedSystemMemory, SharedSystemMemory; public long AdapterLuid; } [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int EnumAdapters(IntPtr factory, uint index, out IntPtr adapter); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int GetDesc(IntPtr adapter, out AdapterDesc desc); [DllImport("dxgi.dll")] private static extern int CreateDXGIFactory1(ref Guid iid, out IntPtr factory); [DllImport("d3d11.dll")] private static extern int D3D11CreateDevice(IntPtr adapter, uint driverType, IntPtr software, uint flags, IntPtr levels, uint levelCount, uint sdkVersion, out IntPtr device, out uint featureLevel, out IntPtr context); public static AdapterResult[] Check() { var results = new List(); var iid = new Guid("770aae78-f26f-4dba-a829-253c83d1b387"); IntPtr factory; Marshal.ThrowExceptionForHR(CreateDXGIFactory1(ref iid, out factory)); try { var table = Marshal.ReadIntPtr(factory); var enumerate = (EnumAdapters)Marshal.GetDelegateForFunctionPointer( Marshal.ReadIntPtr(table, 7 * IntPtr.Size), typeof(EnumAdapters)); for (uint i = 0; i < 32; i++) { IntPtr adapter; int hr = enumerate(factory, i, out adapter); if (hr == unchecked((int)0x887A0002)) break; Marshal.ThrowExceptionForHR(hr); try { var descMethod = (GetDesc)Marshal.GetDelegateForFunctionPointer( Marshal.ReadIntPtr(Marshal.ReadIntPtr(adapter), 8 * IntPtr.Size), typeof(GetDesc)); AdapterDesc desc; Marshal.ThrowExceptionForHR(descMethod(adapter, out desc)); if (desc.VendorId != 0x10de) continue; IntPtr device, context; uint level; hr = D3D11CreateDevice(adapter, 0, IntPtr.Zero, 0, IntPtr.Zero, 0, 7, out device, out level, out context); if (context != IntPtr.Zero) Marshal.Release(context); if (device != IntPtr.Zero) Marshal.Release(device); results.Add(new AdapterResult { Name = desc.Description, VendorId = desc.VendorId, DeviceResult = hr }); } finally { Marshal.Release(adapter); } } } finally { Marshal.Release(factory); } return results.ToArray(); } } }