vdi-cloud/tools/probe-nvidia-d3d.cs

68 lines
3.4 KiB
C#

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