master ohmu/fastfetch-openbsd / src / detection / gpu / d3dkmthk.h
ohmu  ·  2026-10-15
  1#pragma once
  2
  3#include <stdint.h>
  4#include <limits.h>
  5#include <assert.h>
  6#include <stdalign.h>
  7
  8#if _WIN32
  9    #include <ntdef.h>
 10    #include <windef.h>
 11#else
 12    #include <sys/ioctl.h>
 13    #include <uchar.h>
 14    #include <errno.h>
 15
 16typedef struct _LUID {
 17    uint32_t LowPart;
 18    uint32_t HighPart;
 19} LUID;
 20
 21typedef uint32_t UINT;
 22typedef uint64_t ULONGLONG;
 23typedef uint64_t UINT64;
 24typedef uint32_t UINT32;
 25typedef uint16_t UINT16;
 26typedef uint32_t ULONG;
 27typedef uint16_t USHORT;
 28typedef uint8_t UCHAR;
 29typedef void VOID;
 30typedef char16_t WCHAR;
 31typedef void* HANDLE;
 32typedef uint8_t BYTE;
 33typedef int32_t BOOL;
 34typedef uint8_t BOOLEAN;
 35typedef union {
 36    struct {
 37        uint32_t LowPart;
 38        int32_t HighPart;
 39    } u;
 40    int64_t QuadPart;
 41} LARGE_INTEGER;
 42typedef int32_t NTSTATUS; // 0 for success, -1 for failure
 43    #define NT_SUCCESS(Status) ((NTSTATUS) (Status) >= 0)
 44    #define _In_range_(low, hi)
 45#endif
 46
 47#define D3DKMT_ALIGN64 alignas(8)
 48
 49typedef struct D3DKMT_HANDLE {
 50    union {
 51        struct {
 52            uint32_t Instance : 6;
 53            uint32_t Index : 24;
 54            uint32_t Unique : 2;
 55        };
 56        uint32_t Value;
 57    };
 58} D3DKMT_HANDLE;
 59
 60typedef struct _D3DKMT_OPENADAPTERFROMLUID {
 61    LUID AdapterLuid;
 62    D3DKMT_HANDLE hAdapter;
 63} D3DKMT_OPENADAPTERFROMLUID;
 64
 65typedef struct _D3DKMT_ADAPTERINFO {
 66    D3DKMT_HANDLE hAdapter;
 67    LUID AdapterLuid;
 68    ULONG NumOfSources;
 69    BOOL bPrecisePresentRegionsPreferred;
 70} D3DKMT_ADAPTERINFO;
 71
 72#define MAX_ENUM_ADAPTERS 16
 73typedef struct _D3DKMT_ENUMADAPTERS {
 74    _In_range_(0, MAX_ENUM_ADAPTERS) ULONG NumAdapters;
 75    D3DKMT_ADAPTERINFO Adapters[MAX_ENUM_ADAPTERS];
 76} D3DKMT_ENUMADAPTERS;
 77
 78typedef struct _D3DKMT_ENUMADAPTERS2 {
 79    ULONG NumAdapters;             // in/out: On input, the count of the pAdapters array buffer.  On output, the number of adapters enumerated.
 80    D3DKMT_ADAPTERINFO* pAdapters; // out: Array of enumerated adapters containing NumAdapters elements
 81} D3DKMT_ENUMADAPTERS2;
 82static_assert(sizeof(D3DKMT_ENUMADAPTERS2) ==
 83#if SIZE_MAX == UINT64_MAX
 84        0x10
 85#else
 86        0x08
 87#endif
 88    ,
 89    "D3DKMT_ENUMADAPTERS2 structure size mismatch");
 90
 91typedef struct _D3DKMT_ADAPTERREGISTRYINFO {
 92    WCHAR AdapterString[260];
 93    WCHAR BiosString[260];
 94    WCHAR DacType[260];
 95    WCHAR ChipType[260];
 96} D3DKMT_ADAPTERREGISTRYINFO;
 97
 98typedef struct _D3DKMT_CLOSEADAPTER {
 99    D3DKMT_HANDLE hAdapter; // in: adapter handle
100} D3DKMT_CLOSEADAPTER;
101
102typedef struct _D3DKMT_SEGMENTSIZEINFO {
103    D3DKMT_ALIGN64 ULONGLONG DedicatedVideoMemorySize;
104    D3DKMT_ALIGN64 ULONGLONG DedicatedSystemMemorySize;
105    D3DKMT_ALIGN64 ULONGLONG SharedSystemMemorySize;
106} D3DKMT_SEGMENTSIZEINFO;
107
108typedef struct _D3DKMT_ADAPTERTYPE {
109    union {
110        struct {
111            UINT RenderSupported : 1; // WDDM 1.2, Windows 8
112            UINT DisplaySupported : 1;
113            UINT SoftwareDevice : 1;
114            UINT PostDevice : 1;
115            UINT HybridDiscrete : 1; // WDDM 1.3, Windows 8.1
116            UINT HybridIntegrated : 1;
117            UINT IndirectDisplayDevice : 1;
118            UINT Paravirtualized : 1; // WDDM 2.3, Windows 10 Fall Creators Update (version 1709)
119            UINT ACGSupported : 1;
120            UINT SupportSetTimingsFromVidPn : 1;
121            UINT Detachable : 1;
122            UINT ComputeOnly : 1; // WDDM 2.6, Windows 10 May 2019 Update (Version 1903)
123            UINT Prototype : 1;
124            UINT RuntimePowerManagement : 1; // WDDM 2.9, Windows 10 Insider Preview "Iron"
125            UINT Reserved : 18;
126        };
127        UINT Value;
128    };
129} D3DKMT_ADAPTERTYPE;
130
131typedef struct _D3DKMT_ADAPTERADDRESS {
132    UINT BusNumber;      // Bus number on which the physical device is located.
133    UINT DeviceNumber;   // Index of the physical device on the bus.
134    UINT FunctionNumber; // Function number of the adapter on the physical device.
135} D3DKMT_ADAPTERADDRESS;
136
137typedef struct _D3DKMT_DEVICE_IDS {
138    UINT VendorID;
139    UINT DeviceID;
140    UINT SubVendorID;
141    UINT SubSystemID;
142    UINT RevisionID;
143    UINT BusType;
144} D3DKMT_DEVICE_IDS;
145
146typedef struct _D3DKMT_UMD_DRIVER_VERSION {
147    D3DKMT_ALIGN64 LARGE_INTEGER DriverVersion;
148} D3DKMT_UMD_DRIVER_VERSION;
149
150typedef struct _D3DKMT_QUERY_DEVICE_IDS {
151    UINT PhysicalAdapterIndex;   // in:
152    D3DKMT_DEVICE_IDS DeviceIds; // out:
153} D3DKMT_QUERY_DEVICE_IDS;
154
155typedef enum _D3DKMT_PNP_KEY_TYPE {
156    D3DKMT_PNP_KEY_HARDWARE,
157    D3DKMT_PNP_KEY_SOFTWARE
158} D3DKMT_PNP_KEY_TYPE;
159
160typedef struct _D3DKMT_QUERY_PHYSICAL_ADAPTER_PNP_KEY {
161    UINT PhysicalAdapterIndex;
162    D3DKMT_PNP_KEY_TYPE PnPKeyType;
163    WCHAR* pDest;
164    UINT* pCchDest;
165} D3DKMT_QUERY_PHYSICAL_ADAPTER_PNP_KEY;
166
167typedef enum _QAI_DRIVERVERSION {
168    KMT_DRIVERVERSION_WDDM_1_0 = 1000,            // Windows Vista
169    KMT_DRIVERVERSION_WDDM_1_1_PRERELEASE = 1102, // Windows Vista with prereleased Win7 features
170    KMT_DRIVERVERSION_WDDM_1_1 = 1105,            // Windows 7
171    KMT_DRIVERVERSION_WDDM_1_2 = 1200,            // Windows 8
172    KMT_DRIVERVERSION_WDDM_1_3 = 1300,            // Windows 8.1
173    KMT_DRIVERVERSION_WDDM_2_0 = 2000,            // Windows 10
174    KMT_DRIVERVERSION_WDDM_2_1 = 2100,            // Windows 10 (1607)
175    KMT_DRIVERVERSION_WDDM_2_2 = 2200,            // Windows 10 (1703)
176    KMT_DRIVERVERSION_WDDM_2_3 = 2300,            // Windows 10 (1709)
177    KMT_DRIVERVERSION_WDDM_2_4 = 2400,            // Windows 10 (1803)
178    KMT_DRIVERVERSION_WDDM_2_5 = 2500,            // Windows 10 (1809)
179    KMT_DRIVERVERSION_WDDM_2_6 = 2600,            // Windows 10 (1903)
180    KMT_DRIVERVERSION_WDDM_2_7 = 2700,            // Windows 10 (2004)
181    KMT_DRIVERVERSION_WDDM_2_8 = 2800,            // Windows 11 Insider Preview Manganese
182    KMT_DRIVERVERSION_WDDM_2_9 = 2900,            // Windows 11 Insider Preview Iron
183    KMT_DRIVERVERSION_WDDM_3_0 = 3000,            // Windows 11 (21H2)
184    KMT_DRIVERVERSION_WDDM_3_1 = 3100,            // Windows 11 (22H2)
185    KMT_DRIVERVERSION_WDDM_3_2 = 3200,            // Windows 11 (24H2)
186} D3DKMT_DRIVERVERSION;
187
188typedef struct _D3DKMT_QUERY_ADAPTER_UNIQUE_GUID {
189    WCHAR AdapterUniqueGUID[40];
190} D3DKMT_QUERY_ADAPTER_UNIQUE_GUID;
191
192typedef enum _KMTQUERYADAPTERINFOTYPE {
193    KMTQAITYPE_GETSEGMENTSIZE = 3,
194    KMTQAITYPE_ADAPTERGUID = 4,
195    KMTQAITYPE_ADAPTERADDRESS = 6,
196    KMTQAITYPE_ADAPTERREGISTRYINFO = 8,
197    KMTQAITYPE_DRIVERVERSION = 13,
198    KMTQAITYPE_ADAPTERTYPE = 15, // WDDM 1.2, Windows 8
199    KMTQAITYPE_UMD_DRIVER_VERSION = 18,
200    KMTQAITYPE_NODEMETADATA = 25, // WDDM 2.0, Windows 10
201    KMTQAITYPE_PHYSICALADAPTERDEVICEIDS = 31,
202    KMTQAITYPE_PHYSICALADAPTERPNPKEY = 41,     // WDDM 2.2, Windows 10 (1703)
203    KMTQAITYPE_QUERY_ADAPTER_UNIQUE_GUID = 60, // WDDM 2.4, Windows 10 (1803)
204    KMTQAITYPE_NODEPERFDATA = 61,
205    KMTQAITYPE_ADAPTERPERFDATA = 62,
206} KMTQUERYADAPTERINFOTYPE;
207
208typedef struct _D3DKMT_QUERYADAPTERINFO {
209    D3DKMT_HANDLE hAdapter;
210    KMTQUERYADAPTERINFOTYPE Type;
211    VOID* pPrivateDriverData;
212    UINT PrivateDriverDataSize;
213} D3DKMT_QUERYADAPTERINFO;
214
215#define D3DKMT_MAX_SEGMENT_COUNT 32
216
217typedef enum _D3DKMT_MEMORY_SEGMENT_GROUP {
218    D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL = 0,
219    D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL = 1
220} D3DKMT_MEMORY_SEGMENT_GROUP;
221
222typedef enum _D3DKMT_QUERYSTATISTICS_TYPE {
223    D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE = 17, // WDDM 3.1, Windows 11 2022 Update (version 22H2)
224} D3DKMT_QUERYSTATISTICS_TYPE;
225
226typedef struct _D3DKMT_ADAPTER_PERFDATA {
227    UINT32 PhysicalAdapterIndex;                   // in: The physical adapter index, in an LDA chain
228    D3DKMT_ALIGN64 ULONGLONG MemoryFrequency;      // out: Clock frequency of the memory in hertz
229    D3DKMT_ALIGN64 ULONGLONG MaxMemoryFrequency;   // out: Max memory clock frequency
230    D3DKMT_ALIGN64 ULONGLONG MaxMemoryFrequencyOC; // out: Clock frequency of the memory while overclocked in hertz.
231    D3DKMT_ALIGN64 ULONGLONG MemoryBandwidth;      // out: Amount of memory transferred in bytes
232    D3DKMT_ALIGN64 ULONGLONG PCIEBandwidth;        // out: Amount of memory transferred over PCI-E in bytes
233    ULONG FanRPM;                                  // out: Fan rpm
234    ULONG Power;                                   // out: Power draw of the adapter in tenths of a percentage
235    ULONG Temperature;                             // out: Temperature in deci-Celsius 1 = 0.1C
236    UCHAR PowerStateOverride;                      // out: Overrides dxgkrnls power view of linked adapters.
237} D3DKMT_ADAPTER_PERFDATA;
238
239typedef struct _D3DKMT_NODE_PERFDATA {
240    UINT32 NodeOrdinal;                      // in: Node ordinal of the requested engine.
241    UINT32 PhysicalAdapterIndex;             // in: The physical adapter index, in an LDA chain
242    D3DKMT_ALIGN64 ULONGLONG Frequency;      // out: Clock frequency of the engine in hertz
243    D3DKMT_ALIGN64 ULONGLONG MaxFrequency;   // out: Max engine clock frequency
244    D3DKMT_ALIGN64 ULONGLONG MaxFrequencyOC; // out: Max engine over clock frequency
245    ULONG Voltage;                           // out: Voltage of the engine in milli volts mV
246    ULONG VoltageMax;                        // out: Max voltage levels in milli volts.
247    ULONG VoltageMaxOC;                      // out: Max voltage level while overclocked in milli volts.
248    // WDDM 2.5
249    D3DKMT_ALIGN64 ULONGLONG MaxTransitionLatency; // out: Max transition latency to change the frequency in 100 nanoseconds
250} D3DKMT_NODE_PERFDATA;
251
252typedef struct _D3DKMT_QUERYSTATISTICS_MEMORY_USAGE {
253    D3DKMT_ALIGN64 UINT64 AllocatedBytes;
254    D3DKMT_ALIGN64 UINT64 FreeBytes;
255    D3DKMT_ALIGN64 UINT64 ZeroBytes;
256    D3DKMT_ALIGN64 UINT64 ModifiedBytes;
257    D3DKMT_ALIGN64 UINT64 StandbyBytes;
258} D3DKMT_QUERYSTATISTICS_MEMORY_USAGE;
259
260typedef union _D3DKMT_QUERYSTATISTICS_RESULT {
261    D3DKMT_QUERYSTATISTICS_MEMORY_USAGE SegmentGroupUsageInformation;
262    uint8_t Padding[776];
263} D3DKMT_QUERYSTATISTICS_RESULT;
264
265typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT_GROUP_USAGE {
266    UINT16 PhysicalAdapterIndex;
267    UINT16 SegmentGroup; // D3DKMT_MEMORY_SEGMENT_GROUP
268} D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT_GROUP_USAGE;
269
270typedef struct _D3DKMT_QUERYSTATISTICS {
271    D3DKMT_QUERYSTATISTICS_TYPE Type;          // in: type of data requested
272    LUID AdapterLuid;                          // in: adapter to get export / statistics from
273    HANDLE* hProcess;                          // in: process to get statistics for, if required for this query type
274    D3DKMT_QUERYSTATISTICS_RESULT QueryResult; // out: requested data
275
276    union {
277        D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT_GROUP_USAGE QuerySegmentGroupUsage;
278    };
279} D3DKMT_QUERYSTATISTICS;
280static_assert(sizeof(D3DKMT_QUERYSTATISTICS) ==
281#if SIZE_MAX == UINT64_MAX
282        0x328
283#else
284        0x320
285#endif
286    ,
287    "D3DKMT_QUERYSTATISTICS structure size mismatch");
288
289#define DXGK_MAX_METADATA_NAME_LENGTH 32
290typedef enum {
291    DXGK_ENGINE_TYPE_OTHER,
292    DXGK_ENGINE_TYPE_3D,
293    DXGK_ENGINE_TYPE_VIDEO_DECODE,
294    DXGK_ENGINE_TYPE_VIDEO_ENCODE,
295    DXGK_ENGINE_TYPE_VIDEO_PROCESSING,
296    DXGK_ENGINE_TYPE_SCENE_ASSEMBLY,
297    DXGK_ENGINE_TYPE_COPY,
298    DXGK_ENGINE_TYPE_OVERLAY,
299    DXGK_ENGINE_TYPE_CRYPTO,
300    DXGK_ENGINE_TYPE_VIDEO_CODEC,
301    DXGK_ENGINE_TYPE_MAX
302} DXGK_ENGINE_TYPE;
303
304typedef struct _DXGK_NODEMETADATA_FLAGS {
305    union {
306        struct {
307            UINT ContextSchedulingSupported : 1; // WDDM 2.2
308            UINT RingBufferFenceRelease : 1;     // WDDM 2.5
309            UINT SupportTrackedWorkload : 1;
310            UINT UserModeSubmission : 1;
311            UINT SupportBuildTestCommandBuffer : 1; // WDDM 3.2
312            UINT Reserved : 11;
313            UINT MaxInFlightHwQueueBuffers : 16;
314        };
315        UINT32 Value;
316    };
317} DXGK_NODEMETADATA_FLAGS;
318
319typedef struct [[gnu::packed]] _DXGK_NODEMETADATA {
320    DXGK_ENGINE_TYPE EngineType;
321    WCHAR FriendlyName[DXGK_MAX_METADATA_NAME_LENGTH];
322    DXGK_NODEMETADATA_FLAGS Flags; // WDDM 2.2
323    BOOLEAN GpuMmuSupported;       // WDDM 2.0 ???
324    BOOLEAN IoMmuSupported;
325} DXGK_NODEMETADATA;
326
327typedef struct [[gnu::packed]] _D3DKMT_NODEMETADATA {
328    UINT NodeOrdinalAndAdapterIndex; // WDDMv2: High word is physical adapter index, low word is node ordinal
329    DXGK_NODEMETADATA NodeData;
330} D3DKMT_NODEMETADATA;
331static_assert(sizeof(D3DKMT_NODEMETADATA) == 0x4E, "D3DKMT_NODEMETADATA structure size mismatch");
332
333// Functions
334
335#if _WIN32
336
337EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTOpenAdapterFromLuid(_Inout_ CONST D3DKMT_OPENADAPTERFROMLUID*);
338EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTQueryAdapterInfo(_Inout_ CONST D3DKMT_QUERYADAPTERINFO*);
339EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTCloseAdapter(_In_ CONST D3DKMT_CLOSEADAPTER*);
340EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTEnumAdapters(_Inout_ CONST D3DKMT_ENUMADAPTERS*);
341EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTEnumAdapters2(_Inout_ CONST D3DKMT_ENUMADAPTERS2*);
342EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTQueryStatistics(_In_ CONST D3DKMT_QUERYSTATISTICS*);
343
344#else
345
346    // Ref: https://github.com/microsoft/WSL2-Linux-Kernel/blob/linux-msft-wsl-6.6.y/include/uapi/misc/d3dkmthk.h
347    #define LX_DXOPENADAPTERFROMLUID _IOWR(0x47, 0x01, D3DKMT_OPENADAPTERFROMLUID)
348    #define LX_DXQUERYADAPTERINFO _IOWR(0x47, 0x09, D3DKMT_QUERYADAPTERINFO)
349    #define LX_DXENUMADAPTERS2 _IOWR(0x47, 0x14, D3DKMT_ENUMADAPTERS2)
350    #define LX_DXCLOSEADAPTER _IOWR(0x47, 0x15, D3DKMT_CLOSEADAPTER)
351    #define LX_DXQUERYSTATISTICS _IOWR(0x47, 0x43, D3DKMT_QUERYSTATISTICS)
352
353extern int dxgfd; // File descriptor for /dev/dxg, initialized in gpu_wsl.c
354
355static inline NTSTATUS D3DKMTOpenAdapterFromLuid(const D3DKMT_OPENADAPTERFROMLUID* params) {
356    return ioctl(dxgfd, LX_DXOPENADAPTERFROMLUID, params) < 0 ? -errno : 0;
357}
358
359static inline NTSTATUS D3DKMTQueryAdapterInfo(const D3DKMT_QUERYADAPTERINFO* params) {
360    return ioctl(dxgfd, LX_DXQUERYADAPTERINFO, params) < 0 ? -errno : 0;
361}
362
363static inline NTSTATUS D3DKMTCloseAdapter(const D3DKMT_CLOSEADAPTER* params) {
364    return ioctl(dxgfd, LX_DXCLOSEADAPTER, params) < 0 ? -errno : 0;
365}
366
367static inline NTSTATUS D3DKMTEnumAdapters2(D3DKMT_ENUMADAPTERS2* params) {
368    return ioctl(dxgfd, LX_DXENUMADAPTERS2, params) < 0 ? -errno : 0;
369}
370
371static inline NTSTATUS D3DKMTQueryStatistics(const D3DKMT_QUERYSTATISTICS* params) {
372    return ioctl(dxgfd, LX_DXQUERYSTATISTICS, params) < 0 ? -errno : 0;
373}
374
375#endif