Skip to content

Commit 102e8fc

Browse files
committed
GPU (Windows): detect GPU frequency by default
Supported on Windows 11 only
1 parent 8372708 commit 102e8fc

File tree

2 files changed

+116
-7
lines changed

2 files changed

+116
-7
lines changed

src/detection/gpu/gpu_windows.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,39 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
241241
else if (adapterType.HybridIntegrated)
242242
gpu->type = FF_GPU_TYPE_INTEGRATED;
243243
}
244+
245+
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET)
246+
{
247+
for (ULONG nodeIdx = 0; ; nodeIdx++)
248+
{
249+
D3DKMT_NODEMETADATA nodeMetadata = {
250+
.NodeOrdinalAndAdapterIndex = (0 << 16) | nodeIdx,
251+
};
252+
queryAdapterInfo = (D3DKMT_QUERYADAPTERINFO) {
253+
.hAdapter = openAdapterFromLuid.hAdapter,
254+
.Type = KMTQAITYPE_NODEMETADATA,
255+
.pPrivateDriverData = &nodeMetadata,
256+
.PrivateDriverDataSize = sizeof(nodeMetadata),
257+
};
258+
if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) break; // Windows 10 and later
259+
if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D) continue;
260+
261+
D3DKMT_QUERYSTATISTICS queryStatistics = {
262+
.Type = D3DKMT_QUERYSTATISTICS_NODE2,
263+
.AdapterLuid = *(LUID*)&adapterLuid,
264+
.QueryNode2 = { .PhysicalAdapterIndex = 0, .NodeOrdinal = (UINT16) nodeIdx },
265+
};
266+
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) // Windows 11 (22H2) and later
267+
{
268+
gpu->frequency = (uint32_t) (queryStatistics.QueryResult.NodeInformation.NodePerfData.MaxFrequency / 1000 / 1000);
269+
break;
270+
}
271+
}
272+
}
273+
274+
D3DKMT_CLOSEADAPTER closeAdapter = { .hAdapter = openAdapterFromLuid.hAdapter };
275+
(void) D3DKMTCloseAdapter(&closeAdapter);
276+
openAdapterFromLuid.hAdapter = 0;
244277
}
245278

246279
if (options->temp && gpu->temperature != gpu->temperature)
@@ -254,9 +287,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
254287
queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature != 0)
255288
gpu->temperature = queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature / 10.0;
256289
}
257-
258-
D3DKMT_CLOSEADAPTER closeAdapter = { .hAdapter = openAdapterFromLuid.hAdapter };
259-
(void) D3DKMTCloseAdapter(&closeAdapter);
260290
}
261291
}
262292
}

src/util/windows/nt.h

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ typedef struct _D3DKMT_ADAPTERTYPE
7272

7373
typedef enum _KMTQUERYADAPTERINFOTYPE
7474
{
75-
KMTQAITYPE_ADAPTERTYPE = 15,
75+
KMTQAITYPE_ADAPTERTYPE = 15, // WDDM 1.2, Windows 8
76+
KMTQAITYPE_NODEMETADATA = 25, // WDDM 2.0, Windows 10
7677
} KMTQUERYADAPTERINFOTYPE;
7778
typedef struct _D3DKMT_QUERYADAPTERINFO
7879
{
@@ -82,16 +83,21 @@ typedef struct _D3DKMT_QUERYADAPTERINFO
8283
UINT PrivateDriverDataSize;
8384
} D3DKMT_QUERYADAPTERINFO;
8485
EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTQueryAdapterInfo(_Inout_ CONST D3DKMT_QUERYADAPTERINFO*);
85-
#endif
8686

8787
typedef enum _D3DKMT_QUERYSTATISTICS_TYPE
8888
{
8989
D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER = 10, // WDDM 2.4, Windows 10 April 2018 Update (version 1803)
90+
D3DKMT_QUERYSTATISTICS_NODE2 = 18, // WDDM 3.1, Windows 11 2022 Update (version 22H2)
9091
} D3DKMT_QUERYSTATISTICS_TYPE;
9192
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER
9293
{
9394
ULONG PhysicalAdapterIndex;
9495
} D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER;
96+
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_NODE2
97+
{
98+
UINT16 PhysicalAdapterIndex;
99+
UINT16 NodeOrdinal;
100+
} D3DKMT_QUERYSTATISTICS_QUERY_NODE2;
95101
typedef struct _D3DKMT_ADAPTER_PERFDATA
96102
{
97103
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
@@ -128,9 +134,32 @@ typedef struct _D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION
128134
D3DKMT_ADAPTER_PERFDATACAPS AdapterPerfDataCaps;
129135
D3DKMT_GPUVERSION GpuVersion;
130136
} D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION;
137+
typedef struct _D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION {
138+
D3DKMT_ALIGN64 UINT64 Reserved[34];
139+
} D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION;
140+
typedef struct _D3DKMT_NODE_PERFDATA
141+
{
142+
UINT32 NodeOrdinal; // in: Node ordinal of the requested engine.
143+
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
144+
D3DKMT_ALIGN64 ULONGLONG Frequency; // out: Clock frequency of the engine in hertz
145+
D3DKMT_ALIGN64 ULONGLONG MaxFrequency; // out: Max engine clock frequency
146+
D3DKMT_ALIGN64 ULONGLONG MaxFrequencyOC;// out: Max engine over clock frequency
147+
ULONG Voltage; // out: Voltage of the engine in milli volts mV
148+
ULONG VoltageMax; // out: Max voltage levels in milli volts.
149+
ULONG VoltageMaxOC; // out: Max voltage level while overclocked in milli volts.
150+
// WDDM 2.5
151+
D3DKMT_ALIGN64 ULONGLONG MaxTransitionLatency; // out: Max transition latency to change the frequency in 100 nanoseconds
152+
} D3DKMT_NODE_PERFDATA;
153+
typedef struct _D3DKMT_QUERYSTATISTICS_NODE_INFORMATION {
154+
D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION GlobalInformation; //Global statistics
155+
D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION SystemInformation; //Statistics for system thread
156+
D3DKMT_NODE_PERFDATA NodePerfData;
157+
UINT32 Reserved[3];
158+
} D3DKMT_QUERYSTATISTICS_NODE_INFORMATION;
131159
typedef union _D3DKMT_QUERYSTATISTICS_RESULT
132160
{
133-
D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION PhysAdapterInformation; // in: id of physical adapter to get statistics for
161+
D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION PhysAdapterInformation;
162+
D3DKMT_QUERYSTATISTICS_NODE_INFORMATION NodeInformation;
134163
uint8_t Padding[776];
135164
} D3DKMT_QUERYSTATISTICS_RESULT;
136165
typedef struct _D3DKMT_QUERYSTATISTICS
@@ -142,8 +171,58 @@ typedef struct _D3DKMT_QUERYSTATISTICS
142171

143172
union
144173
{
145-
D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER QueryPhysAdapter;
174+
D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER QueryPhysAdapter; // in: id of physical adapter to get statistics for
175+
D3DKMT_QUERYSTATISTICS_QUERY_NODE2 QueryNode2; // in: id of node to get statistics for
146176
};
147177
} D3DKMT_QUERYSTATISTICS;
148178
static_assert(sizeof(D3DKMT_QUERYSTATISTICS) == 0x328, "D3DKMT_QUERYSTATISTICS structure size mismatch");
149179
EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTQueryStatistics(_In_ CONST D3DKMT_QUERYSTATISTICS*);
180+
181+
#define DXGK_MAX_METADATA_NAME_LENGTH 32
182+
typedef enum
183+
{
184+
DXGK_ENGINE_TYPE_OTHER,
185+
DXGK_ENGINE_TYPE_3D,
186+
DXGK_ENGINE_TYPE_VIDEO_DECODE,
187+
DXGK_ENGINE_TYPE_VIDEO_ENCODE,
188+
DXGK_ENGINE_TYPE_VIDEO_PROCESSING,
189+
DXGK_ENGINE_TYPE_SCENE_ASSEMBLY,
190+
DXGK_ENGINE_TYPE_COPY,
191+
DXGK_ENGINE_TYPE_OVERLAY,
192+
DXGK_ENGINE_TYPE_CRYPTO,
193+
DXGK_ENGINE_TYPE_VIDEO_CODEC,
194+
DXGK_ENGINE_TYPE_MAX
195+
} DXGK_ENGINE_TYPE;
196+
typedef struct _DXGK_NODEMETADATA_FLAGS
197+
{
198+
union
199+
{
200+
struct
201+
{
202+
UINT ContextSchedulingSupported : 1; // WDDM 2.2
203+
UINT RingBufferFenceRelease : 1; // WDDM 2.5
204+
UINT SupportTrackedWorkload : 1;
205+
UINT UserModeSubmission : 1;
206+
UINT SupportBuildTestCommandBuffer : 1; // WDDM 3.2
207+
UINT Reserved : 11;
208+
UINT MaxInFlightHwQueueBuffers : 16;
209+
};
210+
UINT32 Value;
211+
};
212+
} DXGK_NODEMETADATA_FLAGS;
213+
typedef struct _DXGK_NODEMETADATA
214+
{
215+
DXGK_ENGINE_TYPE EngineType;
216+
WCHAR FriendlyName[DXGK_MAX_METADATA_NAME_LENGTH];
217+
DXGK_NODEMETADATA_FLAGS Flags; // WDDM 2.2
218+
BOOLEAN GpuMmuSupported; // WDDM 2.0 ???
219+
BOOLEAN IoMmuSupported;
220+
} __attribute__((packed)) DXGK_NODEMETADATA;
221+
typedef struct _D3DKMT_NODEMETADATA
222+
{
223+
_In_ UINT NodeOrdinalAndAdapterIndex; // WDDMv2: High word is physical adapter index, low word is node ordinal
224+
_Out_ DXGK_NODEMETADATA NodeData;
225+
} __attribute__((packed)) D3DKMT_NODEMETADATA;
226+
static_assert(sizeof(D3DKMT_NODEMETADATA) == 0x4E, "D3DKMT_NODEMETADATA structure size mismatch");
227+
228+
#endif

0 commit comments

Comments
 (0)