Skip to content

Commit ab496b2

Browse files
committed
GPU (Windows): greatly improve performance of GPU temp detection
... when `--gpu-driver-specific` is not set. Supported on Windows 10 and later
1 parent 939f428 commit ab496b2

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

src/detection/gpu/gpu_windows.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
164164
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
165165
const char* dllName;
166166

167-
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific))
167+
if (options->driverSpecific && getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName))
168168
{
169169
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
170170
bufferLen = sizeof(buffer);
@@ -242,6 +242,20 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
242242
gpu->type = FF_GPU_TYPE_INTEGRATED;
243243
}
244244
}
245+
246+
if (options->temp && gpu->temperature != gpu->temperature)
247+
{
248+
D3DKMT_QUERYSTATISTICS queryStatistics = {
249+
.Type = D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER,
250+
.AdapterLuid = *(LUID*)&adapterLuid,
251+
.QueryPhysAdapter = { .PhysicalAdapterIndex = 0 },
252+
};
253+
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)))
254+
gpu->temperature = queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature / 10.0;
255+
}
256+
257+
D3DKMT_CLOSEADAPTER closeAdapter = { .hAdapter = openAdapterFromLuid.hAdapter };
258+
(void) D3DKMTCloseAdapter(&closeAdapter);
245259
}
246260
}
247261
}

src/util/windows/nt.h

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <winnt.h>
44
#include <winternl.h>
55

6+
#define D3DKMT_ALIGN64 __attribute__((aligned(8)))
7+
68
typedef struct _PROCESSOR_POWER_INFORMATION {
79
ULONG Number;
810
ULONG MaxMhz;
@@ -48,20 +50,20 @@ typedef struct _D3DKMT_ADAPTERTYPE
4850
{
4951
struct
5052
{
51-
UINT RenderSupported : 1;
53+
UINT RenderSupported : 1; // WDDM 1.2, Windows 8
5254
UINT DisplaySupported : 1;
5355
UINT SoftwareDevice : 1;
5456
UINT PostDevice : 1;
55-
UINT HybridDiscrete : 1;
57+
UINT HybridDiscrete : 1; // WDDM 1.3, Windows 8.1
5658
UINT HybridIntegrated : 1;
5759
UINT IndirectDisplayDevice : 1;
58-
UINT Paravirtualized : 1;
60+
UINT Paravirtualized : 1; // WDDM 2.3, Windows 10 Fall Creators Update (version 1709)
5961
UINT ACGSupported : 1;
6062
UINT SupportSetTimingsFromVidPn : 1;
6163
UINT Detachable : 1;
62-
UINT ComputeOnly : 1;
64+
UINT ComputeOnly : 1; // WDDM 2.6, Windows 10 May 2019 Update (Version 1903)
6365
UINT Prototype : 1;
64-
UINT RuntimePowerManagement : 1;
66+
UINT RuntimePowerManagement : 1; // WDDM 2.9, Windows 10 Insider Preview "Iron"
6567
UINT Reserved : 18;
6668
};
6769
UINT Value;
@@ -81,3 +83,67 @@ typedef struct _D3DKMT_QUERYADAPTERINFO
8183
} D3DKMT_QUERYADAPTERINFO;
8284
EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTQueryAdapterInfo(_Inout_ CONST D3DKMT_QUERYADAPTERINFO*);
8385
#endif
86+
87+
typedef enum _D3DKMT_QUERYSTATISTICS_TYPE
88+
{
89+
D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER = 10, // WDDM 2.4, Windows 10 April 2018 Update (version 1803)
90+
} D3DKMT_QUERYSTATISTICS_TYPE;
91+
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER
92+
{
93+
ULONG PhysicalAdapterIndex;
94+
} D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER;
95+
typedef struct _D3DKMT_ADAPTER_PERFDATA
96+
{
97+
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
98+
D3DKMT_ALIGN64 ULONGLONG MemoryFrequency; // out: Clock frequency of the memory in hertz
99+
D3DKMT_ALIGN64 ULONGLONG MaxMemoryFrequency; // out: Max memory clock frequency
100+
D3DKMT_ALIGN64 ULONGLONG MaxMemoryFrequencyOC; // out: Clock frequency of the memory while overclocked in hertz.
101+
D3DKMT_ALIGN64 ULONGLONG MemoryBandwidth; // out: Amount of memory transferred in bytes
102+
D3DKMT_ALIGN64 ULONGLONG PCIEBandwidth; // out: Amount of memory transferred over PCI-E in bytes
103+
ULONG FanRPM; // out: Fan rpm
104+
ULONG Power; // out: Power draw of the adapter in tenths of a percentage
105+
ULONG Temperature; // out: Temperature in deci-Celsius 1 = 0.1C
106+
UCHAR PowerStateOverride; // out: Overrides dxgkrnls power view of linked adapters.
107+
} D3DKMT_ADAPTER_PERFDATA;
108+
typedef struct _D3DKMT_ADAPTER_PERFDATACAPS
109+
{
110+
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
111+
D3DKMT_ALIGN64 ULONGLONG MaxMemoryBandwidth; // out: Max memory bandwidth in bytes for 1 second
112+
D3DKMT_ALIGN64 ULONGLONG MaxPCIEBandwidth; // out: Max pcie bandwidth in bytes for 1 second
113+
ULONG MaxFanRPM; // out: Max fan rpm
114+
ULONG TemperatureMax; // out: Max temperature before damage levels
115+
ULONG TemperatureWarning; // out: The temperature level where throttling begins.
116+
} D3DKMT_ADAPTER_PERFDATACAPS;
117+
118+
#define DXGK_MAX_GPUVERSION_NAME_LENGTH 32
119+
typedef struct _D3DKMT_GPUVERSION
120+
{
121+
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
122+
WCHAR BiosVersion[DXGK_MAX_GPUVERSION_NAME_LENGTH]; //out: The gpu bios version
123+
WCHAR GpuArchitecture[DXGK_MAX_GPUVERSION_NAME_LENGTH]; //out: The gpu architectures name.
124+
} D3DKMT_GPUVERSION;
125+
typedef struct _D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION
126+
{
127+
D3DKMT_ADAPTER_PERFDATA AdapterPerfData;
128+
D3DKMT_ADAPTER_PERFDATACAPS AdapterPerfDataCaps;
129+
D3DKMT_GPUVERSION GpuVersion;
130+
} D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION;
131+
typedef union _D3DKMT_QUERYSTATISTICS_RESULT
132+
{
133+
D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION PhysAdapterInformation; // in: id of physical adapter to get statistics for
134+
uint8_t Padding[776];
135+
} D3DKMT_QUERYSTATISTICS_RESULT;
136+
typedef struct _D3DKMT_QUERYSTATISTICS
137+
{
138+
D3DKMT_QUERYSTATISTICS_TYPE Type; // in: type of data requested
139+
LUID AdapterLuid; // in: adapter to get export / statistics from
140+
HANDLE* hProcess; // in: process to get statistics for, if required for this query type
141+
D3DKMT_QUERYSTATISTICS_RESULT QueryResult; // out: requested data
142+
143+
union
144+
{
145+
D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER QueryPhysAdapter;
146+
};
147+
} D3DKMT_QUERYSTATISTICS;
148+
static_assert(sizeof(D3DKMT_QUERYSTATISTICS) == 0x328, "D3DKMT_QUERYSTATISTICS structure size mismatch");
149+
EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTQueryStatistics(_In_ CONST D3DKMT_QUERYSTATISTICS*);

0 commit comments

Comments
 (0)