mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 10:24:58 +02:00
GPU (Windows): rewrites with D3DKMT APIs
... which aligns to WSL impl
This commit is contained in:
@@ -99,8 +99,7 @@ typedef struct _D3DKMT_SEGMENTSIZEINFO {
|
||||
|
||||
typedef struct _D3DKMT_ADAPTERTYPE {
|
||||
union {
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
UINT RenderSupported : 1; // WDDM 1.2, Windows 8
|
||||
UINT DisplaySupported : 1;
|
||||
UINT SoftwareDevice : 1;
|
||||
@@ -181,8 +180,11 @@ typedef enum _KMTQUERYADAPTERINFOTYPE {
|
||||
KMTQAITYPE_NODEMETADATA = 25, // WDDM 2.0, Windows 10
|
||||
KMTQAITYPE_PHYSICALADAPTERDEVICEIDS = 31,
|
||||
KMTQAITYPE_QUERY_ADAPTER_UNIQUE_GUID = 60, // WDDM 2.4, Windows 10 (1803)
|
||||
// This reports the GUID string used by the adapter's registry key (DirectX and Video)
|
||||
|
||||
KMTQAITYPE_NODEPERFDATA = 61,
|
||||
KMTQAITYPE_ADAPTERPERFDATA = 62,
|
||||
} KMTQUERYADAPTERINFOTYPE;
|
||||
// `KMTQAITYPE_QUERY_ADAPTER_UNIQUE_GUID` reports the GUID string used by the adapter's registry key (DirectX and Video)
|
||||
|
||||
typedef struct _D3DKMT_QUERYADAPTERINFO {
|
||||
D3DKMT_HANDLE hAdapter;
|
||||
@@ -199,20 +201,9 @@ typedef enum _D3DKMT_MEMORY_SEGMENT_GROUP {
|
||||
} D3DKMT_MEMORY_SEGMENT_GROUP;
|
||||
|
||||
typedef enum _D3DKMT_QUERYSTATISTICS_TYPE {
|
||||
D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER = 10, // WDDM 2.4, Windows 10 April 2018 Update (version 1803)
|
||||
D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE = 17, // WDDM 3.1, Windows 11 2022 Update (version 22H2)
|
||||
D3DKMT_QUERYSTATISTICS_NODE2 = 18,
|
||||
} D3DKMT_QUERYSTATISTICS_TYPE;
|
||||
|
||||
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER {
|
||||
ULONG PhysicalAdapterIndex;
|
||||
} D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER;
|
||||
|
||||
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_NODE2 {
|
||||
UINT16 PhysicalAdapterIndex;
|
||||
UINT16 NodeOrdinal;
|
||||
} D3DKMT_QUERYSTATISTICS_QUERY_NODE2;
|
||||
|
||||
typedef struct _D3DKMT_ADAPTER_PERFDATA {
|
||||
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
|
||||
D3DKMT_ALIGN64 ULONGLONG MemoryFrequency; // out: Clock frequency of the memory in hertz
|
||||
@@ -226,33 +217,6 @@ typedef struct _D3DKMT_ADAPTER_PERFDATA {
|
||||
UCHAR PowerStateOverride; // out: Overrides dxgkrnls power view of linked adapters.
|
||||
} D3DKMT_ADAPTER_PERFDATA;
|
||||
|
||||
typedef struct _D3DKMT_ADAPTER_PERFDATACAPS {
|
||||
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
|
||||
D3DKMT_ALIGN64 ULONGLONG MaxMemoryBandwidth; // out: Max memory bandwidth in bytes for 1 second
|
||||
D3DKMT_ALIGN64 ULONGLONG MaxPCIEBandwidth; // out: Max pcie bandwidth in bytes for 1 second
|
||||
ULONG MaxFanRPM; // out: Max fan rpm
|
||||
ULONG TemperatureMax; // out: Max temperature before damage levels
|
||||
ULONG TemperatureWarning; // out: The temperature level where throttling begins.
|
||||
} D3DKMT_ADAPTER_PERFDATACAPS;
|
||||
|
||||
#define DXGK_MAX_GPUVERSION_NAME_LENGTH 32
|
||||
|
||||
typedef struct _D3DKMT_GPUVERSION {
|
||||
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
|
||||
WCHAR BiosVersion[DXGK_MAX_GPUVERSION_NAME_LENGTH]; // out: The gpu bios version
|
||||
WCHAR GpuArchitecture[DXGK_MAX_GPUVERSION_NAME_LENGTH]; // out: The gpu architectures name.
|
||||
} D3DKMT_GPUVERSION;
|
||||
|
||||
typedef struct _D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION {
|
||||
D3DKMT_ADAPTER_PERFDATA AdapterPerfData;
|
||||
D3DKMT_ADAPTER_PERFDATACAPS AdapterPerfDataCaps;
|
||||
D3DKMT_GPUVERSION GpuVersion;
|
||||
} D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION;
|
||||
|
||||
typedef struct _D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION {
|
||||
D3DKMT_ALIGN64 UINT64 Reserved[34];
|
||||
} D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION;
|
||||
|
||||
typedef struct _D3DKMT_NODE_PERFDATA {
|
||||
UINT32 NodeOrdinal; // in: Node ordinal of the requested engine.
|
||||
UINT32 PhysicalAdapterIndex; // in: The physical adapter index, in an LDA chain
|
||||
@@ -266,13 +230,6 @@ typedef struct _D3DKMT_NODE_PERFDATA {
|
||||
D3DKMT_ALIGN64 ULONGLONG MaxTransitionLatency; // out: Max transition latency to change the frequency in 100 nanoseconds
|
||||
} D3DKMT_NODE_PERFDATA;
|
||||
|
||||
typedef struct _D3DKMT_QUERYSTATISTICS_NODE_INFORMATION {
|
||||
D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION GlobalInformation; // Global statistics
|
||||
D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION SystemInformation; // Statistics for system thread
|
||||
D3DKMT_NODE_PERFDATA NodePerfData;
|
||||
UINT32 Reserved[3];
|
||||
} D3DKMT_QUERYSTATISTICS_NODE_INFORMATION;
|
||||
|
||||
typedef struct _D3DKMT_QUERYSTATISTICS_MEMORY_USAGE {
|
||||
D3DKMT_ALIGN64 UINT64 AllocatedBytes;
|
||||
D3DKMT_ALIGN64 UINT64 FreeBytes;
|
||||
@@ -282,8 +239,6 @@ typedef struct _D3DKMT_QUERYSTATISTICS_MEMORY_USAGE {
|
||||
} D3DKMT_QUERYSTATISTICS_MEMORY_USAGE;
|
||||
|
||||
typedef union _D3DKMT_QUERYSTATISTICS_RESULT {
|
||||
D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION PhysAdapterInformation;
|
||||
D3DKMT_QUERYSTATISTICS_NODE_INFORMATION NodeInformation;
|
||||
D3DKMT_QUERYSTATISTICS_MEMORY_USAGE SegmentGroupUsageInformation;
|
||||
uint8_t Padding[776];
|
||||
} D3DKMT_QUERYSTATISTICS_RESULT;
|
||||
@@ -300,9 +255,7 @@ typedef struct _D3DKMT_QUERYSTATISTICS {
|
||||
D3DKMT_QUERYSTATISTICS_RESULT QueryResult; // out: requested data
|
||||
|
||||
union {
|
||||
D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER QueryPhysAdapter; // in: id of physical adapter to get statistics for
|
||||
D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT_GROUP_USAGE QuerySegmentGroupUsage;
|
||||
D3DKMT_QUERYSTATISTICS_QUERY_NODE2 QueryNode2; // in: id of node to get statistics for
|
||||
};
|
||||
} D3DKMT_QUERYSTATISTICS;
|
||||
static_assert(sizeof(D3DKMT_QUERYSTATISTICS) ==
|
||||
@@ -328,10 +281,10 @@ typedef enum {
|
||||
DXGK_ENGINE_TYPE_VIDEO_CODEC,
|
||||
DXGK_ENGINE_TYPE_MAX
|
||||
} DXGK_ENGINE_TYPE;
|
||||
|
||||
typedef struct _DXGK_NODEMETADATA_FLAGS {
|
||||
union {
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
UINT ContextSchedulingSupported : 1; // WDDM 2.2
|
||||
UINT RingBufferFenceRelease : 1; // WDDM 2.5
|
||||
UINT SupportTrackedWorkload : 1;
|
||||
|
||||
+240
-318
@@ -1,270 +1,163 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#include "common/windows/unicode.h"
|
||||
#include "common/windows/registry.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/windows/nt.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <inttypes.h>
|
||||
#include "d3dkmthk.h"
|
||||
|
||||
#define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}"
|
||||
enum { FF_GUID_STRLEN = sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1 };
|
||||
|
||||
wchar_t regDirectxKey[] = L"SOFTWARE\\Microsoft\\DirectX\\" FF_EMPTY_GUID_STR;
|
||||
const uint32_t regDirectxKeyPrefixLength = (uint32_t) __builtin_strlen("SOFTWARE\\Microsoft\\DirectX\\");
|
||||
wchar_t regDriverKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\" FF_EMPTY_GUID_STR L"\\0000";
|
||||
const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\CurrentControlSet\\Control\\Class\\");
|
||||
|
||||
#define GUID_DEVCLASS_DISPLAY_STRING L"{4d36e968-e325-11ce-bfc1-08002be10318}" // Found in <devguid.h>
|
||||
|
||||
static inline void wrapRegCloseKey(HKEY* phKey) {
|
||||
if (*phKey) {
|
||||
RegCloseKey(*phKey);
|
||||
}
|
||||
}
|
||||
#define FF_HKEY_AUTO_DESTROY __attribute__((__cleanup__(wrapRegCloseKey)))
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) {
|
||||
FF_DEBUG("Starting GPU detection");
|
||||
|
||||
ULONG devIdListSize = 0;
|
||||
if (CM_Get_Device_ID_List_SizeW(&devIdListSize, GUID_DEVCLASS_DISPLAY_STRING, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT) != CR_SUCCESS || devIdListSize <= 1) {
|
||||
FF_DEBUG("No display devices found, list size: %lu", devIdListSize);
|
||||
return "No display devices found";
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
|
||||
D3DKMT_ADAPTERINFO adapters[64];
|
||||
D3DKMT_ENUMADAPTERS2 enumAdapters = {
|
||||
.NumAdapters = ARRAY_SIZE(adapters),
|
||||
.pAdapters = adapters,
|
||||
};
|
||||
NTSTATUS status = D3DKMTEnumAdapters2(&enumAdapters);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
FF_DEBUG("D3DKMTEnumAdapters2 failed: %s", ffDebugNtStatus(status));
|
||||
return "Failed to enumerate adapters with D3DKMTEnumAdapters2";
|
||||
}
|
||||
|
||||
FF_DEBUG("Found device ID list size: %lu", devIdListSize);
|
||||
FF_DEBUG("D3DKMTEnumAdapters2 succeeded, adapter count: %" PRIu32, (uint32_t) enumAdapters.NumAdapters);
|
||||
|
||||
FF_AUTO_FREE DEVINSTID_W devIdList = malloc(devIdListSize * sizeof(*devIdList));
|
||||
for (uint32_t i = 0; i < enumAdapters.NumAdapters; i++) {
|
||||
const D3DKMT_ADAPTERINFO* adapter = &adapters[i];
|
||||
FF_DEBUG("Processing adapter #%u", i);
|
||||
|
||||
if (CM_Get_Device_ID_ListW(GUID_DEVCLASS_DISPLAY_STRING, devIdList, devIdListSize, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT) != CR_SUCCESS) {
|
||||
FF_DEBUG("CM_Get_Device_ID_ListW failed");
|
||||
return "CM_Get_Device_ID_ListW failed";
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED int deviceCount = 0;
|
||||
for (wchar_t* devId = devIdList; *devId; devId += wcslen(devId) + 1) {
|
||||
FF_DEBUG("Processing device ID: %ls", devId);
|
||||
|
||||
DEVINST devInst = 0;
|
||||
|
||||
if (CM_Locate_DevNodeW(&devInst, devId, CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS) {
|
||||
FF_DEBUG("Failed to get device instance ID or locate device node");
|
||||
D3DKMT_ADAPTERTYPE adapterType;
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_ADAPTERTYPE,
|
||||
.pPrivateDriverData = &adapterType,
|
||||
.PrivateDriverDataSize = sizeof(adapterType),
|
||||
});
|
||||
if (!NT_SUCCESS(status)) {
|
||||
FF_DEBUG("KMTQAITYPE_ADAPTERTYPE query failed for adapter #%u: %s", i, ffDebugNtStatus(status));
|
||||
continue;
|
||||
}
|
||||
FF_DEBUG("Device instance ID: %lu", devInst);
|
||||
|
||||
for (wchar_t* p = devId; *p; p++) {
|
||||
if (*p >= L'a' && *p <= L'z') {
|
||||
*p -= L'a' - L'A';
|
||||
}
|
||||
if (adapterType.SoftwareDevice) {
|
||||
FF_DEBUG("Skipping software adapter #%u", i);
|
||||
goto close_adapter;
|
||||
}
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
|
||||
deviceCount++;
|
||||
FF_DEBUG("Added GPU #%d to list", deviceCount);
|
||||
|
||||
FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *gpus);
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
ffStrbufInitStatic(&gpu->platformApi, "CM API");
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = 0;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
gpu->type = adapterType.HybridIntegrated
|
||||
? FF_GPU_TYPE_INTEGRATED
|
||||
: adapterType.HybridDiscrete
|
||||
? FF_GPU_TYPE_DISCRETE
|
||||
: FF_GPU_TYPE_UNKNOWN;
|
||||
|
||||
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
|
||||
if (swscanf(devId, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) {
|
||||
FF_DEBUG("Parsed PCI IDs - Vendor: 0x%x, Device: 0x%x, SubSystem: 0x%x, Rev: 0x%x", vendorId, deviceId, subSystemId, revId);
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
|
||||
const char* vendorStr = NULL;
|
||||
|
||||
D3DKMT_QUERY_DEVICE_IDS deviceIds = { .PhysicalAdapterIndex = 0 };
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_PHYSICALADAPTERDEVICEIDS,
|
||||
.pPrivateDriverData = &deviceIds,
|
||||
.PrivateDriverDataSize = sizeof(deviceIds),
|
||||
});
|
||||
if (NT_SUCCESS(status)) {
|
||||
vendorStr = ffGPUGetVendorString(deviceIds.DeviceIds.VendorID);
|
||||
ffStrbufSetStatic(&gpu->vendor, vendorStr);
|
||||
FF_DEBUG("Adapter #%u vendor/device IDs: vendor=0x%04x device=0x%04x",
|
||||
i,
|
||||
deviceIds.DeviceIds.VendorID,
|
||||
deviceIds.DeviceIds.DeviceID);
|
||||
} else {
|
||||
FF_DEBUG("Failed to parse PCI device information from instance ID");
|
||||
deviceIds.DeviceIds.VendorID = -1u;
|
||||
FF_DEBUG("KMTQAITYPE_PHYSICALADAPTERDEVICEIDS query failed for adapter #%u: %s", i, ffDebugNtStatus(status));
|
||||
}
|
||||
|
||||
uint32_t pciBus = 0, pciAddr = 0, pciDev = 0, pciFunc = 0;
|
||||
|
||||
ULONG pciBufLen = sizeof(pciBus);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_BUSNUMBER, NULL, &pciBus, &pciBufLen, 0) == CR_SUCCESS) {
|
||||
pciBufLen = sizeof(pciAddr);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_ADDRESS, NULL, &pciAddr, &pciBufLen, 0) == CR_SUCCESS) {
|
||||
pciDev = (pciAddr >> 16) & 0xFFFF;
|
||||
pciFunc = pciAddr & 0xFFFF;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc);
|
||||
pciAddr = 1; // Set to 1 to indicate that the device is a PCI device
|
||||
FF_DEBUG("PCI location - Bus: %u, Device: %u, Function: %u, DeviceID: %llu", pciBus, pciDev, pciFunc, gpu->deviceId);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get PCI address");
|
||||
}
|
||||
D3DKMT_ADAPTERADDRESS adapterAddress = {};
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_ADAPTERADDRESS,
|
||||
.pPrivateDriverData = &adapterAddress,
|
||||
.PrivateDriverDataSize = sizeof(adapterAddress),
|
||||
});
|
||||
if (NT_SUCCESS(status)) {
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, adapterAddress.BusNumber, adapterAddress.DeviceNumber, adapterAddress.FunctionNumber);
|
||||
FF_DEBUG("Adapter #%u PCI address: bus=%u device=%u function=%u",
|
||||
i,
|
||||
adapterAddress.BusNumber,
|
||||
adapterAddress.DeviceNumber,
|
||||
adapterAddress.FunctionNumber);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get PCI bus number");
|
||||
adapterAddress.BusNumber = -1u;
|
||||
gpu->deviceId = ffGPUGeneral2Id(((uint64_t) adapter->AdapterLuid.HighPart << 32) | (uint64_t) adapter->AdapterLuid.LowPart);
|
||||
FF_DEBUG("KMTQAITYPE_ADAPTERADDRESS query failed for adapter #%u, fallback to LUID-based deviceId: %s",
|
||||
i,
|
||||
ffDebugNtStatus(status));
|
||||
}
|
||||
|
||||
uint64_t adapterLuid = 0;
|
||||
|
||||
FF_HKEY_AUTO_DESTROY HKEY hVideoIdKey = NULL;
|
||||
|
||||
wchar_t buffer[256];
|
||||
ULONG bufferLen = 0;
|
||||
|
||||
FF_DEBUG("Get device description as device name");
|
||||
bufferLen = sizeof(buffer);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DEVICEDESC, NULL, buffer, &bufferLen, 0) == CR_SUCCESS) {
|
||||
ffStrbufSetWS(&gpu->name, buffer);
|
||||
FF_DEBUG("Found device description: %s", gpu->name.chars);
|
||||
D3DKMT_UMD_DRIVER_VERSION umdDriverVersion;
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_UMD_DRIVER_VERSION,
|
||||
.pPrivateDriverData = &umdDriverVersion,
|
||||
.PrivateDriverDataSize = sizeof(umdDriverVersion),
|
||||
});
|
||||
if (NT_SUCCESS(status)) {
|
||||
ffStrbufSetF(&gpu->driver,
|
||||
"%u.%u.%u.%u",
|
||||
(uint32_t) (umdDriverVersion.DriverVersion.QuadPart >> 48ul & 0xFFFF),
|
||||
(uint32_t) (umdDriverVersion.DriverVersion.QuadPart >> 32ul & 0xFFFF),
|
||||
(uint32_t) (umdDriverVersion.DriverVersion.QuadPart >> 16ul & 0xFFFF),
|
||||
(uint32_t) (umdDriverVersion.DriverVersion.QuadPart >> 0ul & 0xFFFF));
|
||||
FF_DEBUG("Adapter #%u UMD driver version: %08" PRIX64, i, (uint64_t) umdDriverVersion.DriverVersion.QuadPart);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get device description");
|
||||
FF_DEBUG("KMTQAITYPE_UMD_DRIVER_VERSION query failed for adapter #%u: %s", i, ffDebugNtStatus(status));
|
||||
}
|
||||
|
||||
if (wcsncmp(devId, L"SWD\\", 4) == 0 || wcsncmp(devId, L"ROOT\\DISPLAY\\", 13) == 0) {
|
||||
FF_DEBUG("Skipping virtual devices to avoid duplicates");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CM_Open_DevNode_Key(devInst, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &hVideoIdKey, CM_REGISTRY_HARDWARE) == CR_SUCCESS) {
|
||||
FF_DEBUG("Opened device node registry key");
|
||||
bufferLen = sizeof(buffer);
|
||||
if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS &&
|
||||
bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t)) {
|
||||
FF_DEBUG("Found VideoID: %ls", buffer);
|
||||
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN);
|
||||
FF_AUTO_CLOSE_FD HANDLE hDirectxKey = NULL;
|
||||
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) {
|
||||
FF_DEBUG("Opened DirectX registry key");
|
||||
|
||||
if (gpu->vendor.length == 0) {
|
||||
uint32_t vendorId = 0;
|
||||
if (ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) {
|
||||
FF_DEBUG("Found vendor ID from DirectX registry: 0x%x", vendorId);
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
|
||||
}
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0) {
|
||||
FF_DEBUG("Trying to get GPU name from DirectX registry");
|
||||
if (ffRegReadStrbuf(hDirectxKey, L"Description", &gpu->name, NULL)) {
|
||||
FF_DEBUG("Found GPU description: %s", gpu->name.chars);
|
||||
}
|
||||
}
|
||||
|
||||
if (ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &gpu->dedicated.total, NULL)) {
|
||||
FF_DEBUG("Found dedicated video memory: %llu bytes", gpu->dedicated.total);
|
||||
}
|
||||
|
||||
if (ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &gpu->shared.total, NULL)) {
|
||||
FF_DEBUG("Found dedicated system memory: %llu bytes", gpu->shared.total);
|
||||
uint64_t sharedSystemMemory = 0;
|
||||
if (ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL)) {
|
||||
gpu->shared.total += sharedSystemMemory;
|
||||
FF_DEBUG("Added shared system memory: %llu bytes, total shared: %llu bytes", sharedSystemMemory, gpu->shared.total);
|
||||
}
|
||||
}
|
||||
|
||||
if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL)) {
|
||||
FF_DEBUG("Found adapter LUID: %llu", adapterLuid);
|
||||
if (!gpu->deviceId) {
|
||||
gpu->deviceId = ffGPUGeneral2Id(adapterLuid);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t featureLevel = 0;
|
||||
if (ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) {
|
||||
FF_DEBUG("Found D3D12 feature level: 0x%x", featureLevel);
|
||||
ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8);
|
||||
} else if (ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) {
|
||||
FF_DEBUG("Found D3D11 feature level: 0x%x", featureLevel);
|
||||
ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8);
|
||||
}
|
||||
|
||||
uint64_t driverVersion = 0;
|
||||
if (ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion) {
|
||||
FF_DEBUG("Found driver version: %llu", driverVersion);
|
||||
ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u", (unsigned) (driverVersion >> 48) & 0xFFFF, (unsigned) (driverVersion >> 32) & 0xFFFF, (unsigned) (driverVersion >> 16) & 0xFFFF, (unsigned) (driverVersion >> 0) & 0xFFFF);
|
||||
}
|
||||
} else {
|
||||
FF_DEBUG("Failed to open DirectX registry key");
|
||||
}
|
||||
} else {
|
||||
FF_DEBUG("Failed to get VideoID or invalid buffer length");
|
||||
}
|
||||
D3DKMT_DRIVERVERSION wddmVersion = KMT_DRIVERVERSION_WDDM_3_0;
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_DRIVERVERSION,
|
||||
.pPrivateDriverData = &wddmVersion,
|
||||
.PrivateDriverDataSize = sizeof(wddmVersion),
|
||||
});
|
||||
if (NT_SUCCESS(status)) {
|
||||
ffStrbufSetF(&gpu->platformApi, "WDDM %u.%u", (uint32_t) wddmVersion / 1000, ((uint32_t) wddmVersion % 1000) / 100);
|
||||
FF_DEBUG("Adapter #%u WDDM version: %u", i, (uint32_t) wddmVersion);
|
||||
} else {
|
||||
FF_DEBUG("Failed to open device node registry key");
|
||||
}
|
||||
|
||||
if (gpu->vendor.length == 0 || gpu->name.length == 0 || gpu->driver.length == 0 || gpu->dedicated.total == FF_GPU_VMEM_SIZE_UNSET) {
|
||||
FF_DEBUG("Trying fallback registry method for vendor/name etc.");
|
||||
bufferLen = sizeof(buffer);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DRIVER, NULL, buffer, &bufferLen, 0) == CR_SUCCESS &&
|
||||
bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2) {
|
||||
FF_DEBUG("Found driver GUID: %ls", buffer);
|
||||
wmemcpy(regDriverKey + regDriverKeyPrefixLength, buffer, FF_GUID_STRLEN + strlen("\\0000"));
|
||||
FF_AUTO_CLOSE_FD HANDLE hRegDriverKey = NULL;
|
||||
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDriverKey, &hRegDriverKey, NULL)) {
|
||||
FF_DEBUG("Opened driver registry key");
|
||||
|
||||
if (gpu->vendor.length == 0 && ffRegReadStrbuf(hRegDriverKey, L"ProviderName", &gpu->vendor, NULL)) {
|
||||
FF_DEBUG("Found provider name: %s", gpu->vendor.chars);
|
||||
if (ffStrbufContainS(&gpu->vendor, "Intel")) {
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
} else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) {
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
} else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) {
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
}
|
||||
}
|
||||
if (gpu->name.length == 0 && ffRegReadStrbuf(hRegDriverKey, L"DriverDesc", &gpu->name, NULL)) {
|
||||
FF_DEBUG("Found driver description: %s", gpu->name.chars);
|
||||
}
|
||||
if (gpu->driver.length == 0 && ffRegReadStrbuf(hRegDriverKey, L"DriverVersion", &gpu->driver, NULL)) {
|
||||
FF_DEBUG("Found driver version: %s", gpu->driver.chars);
|
||||
}
|
||||
if (gpu->dedicated.total == FF_GPU_VMEM_SIZE_UNSET) {
|
||||
if (!ffRegReadUint64(hRegDriverKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL)) {
|
||||
uint32_t memorySize = 0;
|
||||
if (ffRegReadUint(hRegDriverKey, L"HardwareInformation.MemorySize", &memorySize, NULL)) {
|
||||
gpu->dedicated.total = memorySize;
|
||||
FF_DEBUG("Found memory size from hardware info: %u bytes", memorySize);
|
||||
}
|
||||
} else {
|
||||
FF_DEBUG("Found qwMemorySize from hardware info: %llu bytes", gpu->dedicated.total);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FF_DEBUG("Failed to open driver registry key");
|
||||
}
|
||||
} else {
|
||||
FF_DEBUG("Failed to get driver GUID or invalid buffer length");
|
||||
}
|
||||
ffStrbufSetStatic(&gpu->platformApi, "WDDM");
|
||||
FF_DEBUG("KMTQAITYPE_DRIVERVERSION query failed for adapter #%u", i);
|
||||
}
|
||||
|
||||
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
|
||||
const char* dllName;
|
||||
|
||||
if (options->driverSpecific && getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName)) {
|
||||
FF_DEBUG("Calling driver-specific detection function for vendor: %s, DLL: %s", gpu->vendor.chars, dllName);
|
||||
FF_MAYBE_UNUSED const char* error = detectFn(
|
||||
&(FFGpuDriverCondition) {
|
||||
.type = (deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID : 0) | (adapterLuid > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0) | (pciAddr > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0),
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_LUID |
|
||||
(deviceIds.DeviceIds.VendorID != -1u ? FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID : 0) |
|
||||
(adapterAddress.BusNumber != -1u ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0),
|
||||
.pciDeviceId = {
|
||||
.deviceId = deviceId,
|
||||
.vendorId = vendorId,
|
||||
.subSystemId = subSystemId,
|
||||
.revId = revId,
|
||||
.deviceId = deviceIds.DeviceIds.DeviceID,
|
||||
.vendorId = deviceIds.DeviceIds.VendorID,
|
||||
.subSystemId = deviceIds.DeviceIds.SubSystemID,
|
||||
.revId = deviceIds.DeviceIds.RevisionID,
|
||||
},
|
||||
.pciBusId = {
|
||||
.domain = 0,
|
||||
.bus = pciBus,
|
||||
.device = pciDev,
|
||||
.func = pciFunc,
|
||||
.bus = adapterAddress.BusNumber,
|
||||
.device = adapterAddress.DeviceNumber,
|
||||
.func = adapterAddress.FunctionNumber,
|
||||
},
|
||||
.luid = adapterLuid,
|
||||
.luid = ((uint64_t) adapter->AdapterLuid.HighPart << 32) | (uint64_t) adapter->AdapterLuid.LowPart,
|
||||
},
|
||||
(FFGpuDriverResult) {
|
||||
.index = &gpu->index,
|
||||
@@ -284,123 +177,139 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
FF_DEBUG("No driver-specific detection function found for vendor: %s", gpu->vendor.chars);
|
||||
}
|
||||
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN && adapterLuid > 0) {
|
||||
FF_DEBUG("Trying to determine GPU type using D3DKMT APIs");
|
||||
D3DKMT_OPENADAPTERFROMLUID openAdapterFromLuid = { .AdapterLuid = *(LUID*) &adapterLuid };
|
||||
if (NT_SUCCESS(D3DKMTOpenAdapterFromLuid(&openAdapterFromLuid))) {
|
||||
FF_DEBUG("Successfully opened adapter from LUID");
|
||||
|
||||
D3DKMT_ADAPTERTYPE adapterType = {};
|
||||
D3DKMT_QUERYADAPTERINFO queryAdapterInfo = {
|
||||
.hAdapter = openAdapterFromLuid.hAdapter,
|
||||
.Type = KMTQAITYPE_ADAPTERTYPE, // Windows 8 and later
|
||||
.pPrivateDriverData = &adapterType,
|
||||
.PrivateDriverDataSize = sizeof(adapterType),
|
||||
};
|
||||
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) {
|
||||
FF_DEBUG("Queried adapter type - HybridDiscrete: %d, HybridIntegrated: %d", adapterType.HybridDiscrete, adapterType.HybridIntegrated);
|
||||
if (adapterType.HybridDiscrete) {
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
} else if (adapterType.HybridIntegrated) {
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
} else {
|
||||
FF_DEBUG("Failed to query adapter type");
|
||||
}
|
||||
|
||||
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET && ffIsWindows11OrGreater()) {
|
||||
FF_DEBUG("Trying to get GPU frequency information");
|
||||
for (ULONG nodeIdx = 0;; nodeIdx++) {
|
||||
D3DKMT_NODEMETADATA nodeMetadata = {
|
||||
.NodeOrdinalAndAdapterIndex = (0 << 16) | nodeIdx,
|
||||
};
|
||||
queryAdapterInfo = (D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = openAdapterFromLuid.hAdapter,
|
||||
.Type = KMTQAITYPE_NODEMETADATA, // Windows 10 and later
|
||||
.pPrivateDriverData = &nodeMetadata,
|
||||
.PrivateDriverDataSize = sizeof(nodeMetadata),
|
||||
};
|
||||
if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) {
|
||||
FF_DEBUG("No more nodes to query (index %lu)", nodeIdx);
|
||||
break;
|
||||
}
|
||||
if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D) {
|
||||
FF_DEBUG("Skipping node %lu (not 3D engine)", nodeIdx);
|
||||
continue;
|
||||
}
|
||||
|
||||
D3DKMT_QUERYSTATISTICS queryStatistics = {
|
||||
.Type = D3DKMT_QUERYSTATISTICS_NODE2, // Windows 11 (22H2) and later
|
||||
.AdapterLuid = *(LUID*) &adapterLuid,
|
||||
.QueryNode2 = { .PhysicalAdapterIndex = 0, .NodeOrdinal = (UINT16) nodeIdx },
|
||||
};
|
||||
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) {
|
||||
gpu->frequency = (uint32_t) (queryStatistics.QueryResult.NodeInformation.NodePerfData.MaxFrequency / 1000 / 1000);
|
||||
FF_DEBUG("Found GPU frequency: %u MHz", gpu->frequency);
|
||||
break;
|
||||
} else {
|
||||
FF_DEBUG("Failed to query node statistics for node %lu", nodeIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3DKMT_CLOSEADAPTER closeAdapter = { .hAdapter = openAdapterFromLuid.hAdapter };
|
||||
(void) D3DKMTCloseAdapter(&closeAdapter);
|
||||
openAdapterFromLuid.hAdapter = (D3DKMT_HANDLE) {};
|
||||
FF_DEBUG("Closed adapter handle");
|
||||
if (gpu->name.length == 0) {
|
||||
D3DKMT_ADAPTERREGISTRYINFO registryInfo;
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_ADAPTERREGISTRYINFO,
|
||||
.pPrivateDriverData = ®istryInfo,
|
||||
.PrivateDriverDataSize = sizeof(registryInfo),
|
||||
});
|
||||
if (NT_SUCCESS(status)) {
|
||||
ffStrbufSetWS(&gpu->name, registryInfo.AdapterString);
|
||||
FF_DEBUG("Adapter #%u adapter string: %s", i, gpu->name.chars);
|
||||
} else {
|
||||
FF_DEBUG("Failed to open adapter from LUID");
|
||||
FF_DEBUG("KMTQAITYPE_ADAPTERREGISTRYINFO query failed for adapter #%u: %s", i, ffDebugNtStatus(status));
|
||||
}
|
||||
}
|
||||
|
||||
if (options->temp && gpu->temperature == FF_GPU_TEMP_UNSET && ffIsWindows10OrGreater()) {
|
||||
FF_DEBUG("Trying to get GPU temperature");
|
||||
D3DKMT_QUERYSTATISTICS queryStatistics = {
|
||||
.Type = D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER, // Windows 10 (1803) and later
|
||||
.AdapterLuid = *(LUID*) &adapterLuid,
|
||||
.QueryPhysAdapter = { .PhysicalAdapterIndex = 0 },
|
||||
};
|
||||
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)) &&
|
||||
queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature != 0) {
|
||||
gpu->temperature = queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature / 10.0;
|
||||
FF_DEBUG("Found GPU temperature: %.1f°C", gpu->temperature);
|
||||
} else {
|
||||
FF_DEBUG("Failed to get GPU temperature or temperature is 0");
|
||||
}
|
||||
}
|
||||
|
||||
if (options->driverSpecific && gpu->dedicated.used == FF_GPU_VMEM_SIZE_UNSET && ffIsWindows11OrGreater()) {
|
||||
FF_DEBUG("Trying to get used video memory from D3DKMT method");
|
||||
if (gpu->dedicated.total == FF_GPU_VMEM_SIZE_UNSET && gpu->shared.total == FF_GPU_VMEM_SIZE_UNSET) {
|
||||
if (wddmVersion >= KMT_DRIVERVERSION_WDDM_3_1 && options->driverSpecific) {
|
||||
// Supports memory usage query; requires Windows 11 (22H2) or later
|
||||
D3DKMT_QUERYSTATISTICS queryStatistics = {
|
||||
.Type = D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE,
|
||||
.AdapterLuid = *(LUID*) &adapterLuid,
|
||||
.AdapterLuid = adapter->AdapterLuid,
|
||||
.QuerySegmentGroupUsage = {
|
||||
.PhysicalAdapterIndex = 0,
|
||||
.SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL,
|
||||
},
|
||||
};
|
||||
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) {
|
||||
status = D3DKMTQueryStatistics(&queryStatistics);
|
||||
if (NT_SUCCESS(status)) {
|
||||
D3DKMT_QUERYSTATISTICS_MEMORY_USAGE* info = &queryStatistics.QueryResult.SegmentGroupUsageInformation;
|
||||
uint64_t used = info->AllocatedBytes + info->ModifiedBytes + info->StandbyBytes;
|
||||
uint64_t total = used + info->FreeBytes + info->ZeroBytes;
|
||||
gpu->dedicated.used = used;
|
||||
gpu->dedicated.total = total;
|
||||
|
||||
FF_DEBUG("Found local memory size %llu / %llu", used, total);
|
||||
FF_DEBUG("Adapter #%u local memory usage: used=%" PRIu64 " total=%" PRIu64, i, used, total);
|
||||
} else {
|
||||
FF_DEBUG("Failed to query segment group usage for local memory");
|
||||
FF_DEBUG("D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE (LOCAL) failed for adapter #%u: %s",
|
||||
i,
|
||||
ffDebugNtStatus(status));
|
||||
}
|
||||
|
||||
queryStatistics.QuerySegmentGroupUsage.SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL;
|
||||
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) {
|
||||
status = D3DKMTQueryStatistics(&queryStatistics);
|
||||
if (NT_SUCCESS(status)) {
|
||||
D3DKMT_QUERYSTATISTICS_MEMORY_USAGE* info = &queryStatistics.QueryResult.SegmentGroupUsageInformation;
|
||||
uint64_t used = info->AllocatedBytes + info->ModifiedBytes + info->StandbyBytes;
|
||||
uint64_t total = used + info->FreeBytes + info->ZeroBytes;
|
||||
gpu->shared.used = used;
|
||||
gpu->shared.total = total;
|
||||
|
||||
FF_DEBUG("Found non-local memory size %llu / %llu", used, total);
|
||||
FF_DEBUG("Adapter #%u non-local memory usage: used=%" PRIu64 " total=%" PRIu64, i, used, total);
|
||||
} else {
|
||||
FF_DEBUG("Failed to query segment group usage for non-local memory");
|
||||
FF_DEBUG("D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE (NON_LOCAL) failed for adapter #%u: %s",
|
||||
i,
|
||||
ffDebugNtStatus(status));
|
||||
}
|
||||
} else {
|
||||
// Supports basic segment (total) size query
|
||||
D3DKMT_SEGMENTSIZEINFO segmentSizeInfo = {};
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_GETSEGMENTSIZE,
|
||||
.pPrivateDriverData = &segmentSizeInfo,
|
||||
.PrivateDriverDataSize = sizeof(segmentSizeInfo),
|
||||
});
|
||||
if (NT_SUCCESS(status)) {
|
||||
FF_DEBUG("Adapter #%u segment size - DedicatedVideoMemorySize: %" PRIu64
|
||||
", DedicatedSystemMemorySize: %" PRIu64 ", SharedSystemMemorySize: %" PRIu64,
|
||||
i,
|
||||
(uint64_t) segmentSizeInfo.DedicatedVideoMemorySize,
|
||||
(uint64_t) segmentSizeInfo.DedicatedSystemMemorySize,
|
||||
(uint64_t) segmentSizeInfo.SharedSystemMemorySize);
|
||||
gpu->dedicated.total = segmentSizeInfo.DedicatedVideoMemorySize;
|
||||
gpu->shared.total = segmentSizeInfo.DedicatedSystemMemorySize + segmentSizeInfo.SharedSystemMemorySize;
|
||||
} else {
|
||||
FF_DEBUG("Failed to query segment size information for adapter #%u: %s", i, ffDebugNtStatus(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wddmVersion >= KMT_DRIVERVERSION_WDDM_2_4) {
|
||||
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET) {
|
||||
for (uint32_t nodeIdx = 0;; nodeIdx++) {
|
||||
D3DKMT_NODEMETADATA nodeMetadata = {
|
||||
.NodeOrdinalAndAdapterIndex = (0 << 16) | nodeIdx,
|
||||
};
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_NODEMETADATA,
|
||||
.pPrivateDriverData = &nodeMetadata,
|
||||
.PrivateDriverDataSize = sizeof(nodeMetadata),
|
||||
});
|
||||
if (!NT_SUCCESS(status)) { break; }
|
||||
|
||||
if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D) { continue; }
|
||||
|
||||
D3DKMT_NODE_PERFDATA nodePerfData = {
|
||||
.NodeOrdinal = nodeIdx,
|
||||
.PhysicalAdapterIndex = 0,
|
||||
};
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_NODEPERFDATA,
|
||||
.pPrivateDriverData = &nodePerfData,
|
||||
.PrivateDriverDataSize = sizeof(nodePerfData),
|
||||
});
|
||||
if (NT_SUCCESS(status)) {
|
||||
gpu->frequency = (uint32_t) (nodePerfData.MaxFrequency / 1000 / 1000);
|
||||
FF_DEBUG("Adapter #%u max graphics frequency: %u MHz", i, gpu->frequency);
|
||||
break;
|
||||
} else {
|
||||
FF_DEBUG("Failed to query node performance data for adapter #%u node #%u: %s",
|
||||
i,
|
||||
nodeIdx,
|
||||
ffDebugNtStatus(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->temp && gpu->temperature == FF_GPU_TEMP_UNSET) {
|
||||
D3DKMT_ADAPTER_PERFDATA adapterPerfData = {
|
||||
.PhysicalAdapterIndex = 0,
|
||||
};
|
||||
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_ADAPTERPERFDATA,
|
||||
.pPrivateDriverData = &adapterPerfData,
|
||||
.PrivateDriverDataSize = sizeof(adapterPerfData),
|
||||
});
|
||||
if (NT_SUCCESS(status)) {
|
||||
gpu->temperature = adapterPerfData.Temperature / 10.0;
|
||||
FF_DEBUG("Adapter #%u temperature: %.1f°C", i, gpu->temperature);
|
||||
} else {
|
||||
FF_DEBUG("Failed to query temperature for adapter #%u: %s", i, ffDebugNtStatus(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -414,9 +323,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) {
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) { gpu->type = FF_GPU_TYPE_DISCRETE; }
|
||||
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) {
|
||||
// 0000:00:02.0 is reserved for Intel integrated graphics
|
||||
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
@@ -424,18 +331,33 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
|
||||
if (gpu->type != FF_GPU_TYPE_UNKNOWN) {
|
||||
FF_DEBUG("Determined GPU type based on vendor (%s) and name: %u", gpu->vendor.chars, gpu->type);
|
||||
} else if (ffIsWindows10OrGreater()) {
|
||||
}
|
||||
#if _WIN32
|
||||
else if (ffIsWindows10OrGreater()) {
|
||||
const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult * gpu);
|
||||
FF_MAYBE_UNUSED const char* error = ffGPUDetectTypeWithDXCore(*(LUID*) &adapterLuid, gpu);
|
||||
FF_MAYBE_UNUSED const char* error = ffGPUDetectTypeWithDXCore(adapter->AdapterLuid, gpu);
|
||||
FF_DEBUG("DXCore GPU type detection result: %s", error ?: "Success");
|
||||
} else {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
FF_DEBUG("Unable to determine GPU type by any method for this adapter");
|
||||
}
|
||||
}
|
||||
|
||||
FF_DEBUG("Completed processing GPU #%d - Vendor: %s, Name: %s, Type: %d", deviceCount, gpu->vendor.chars, gpu->name.chars, gpu->type);
|
||||
FF_DEBUG("Adapter #%u summary: name='%s', vendor='%s', type=%u, deviceId=%" PRIu64,
|
||||
i,
|
||||
gpu->name.length ? gpu->name.chars : "unknown",
|
||||
gpu->vendor.length ? gpu->vendor.chars : "unknown",
|
||||
(uint32_t) gpu->type,
|
||||
(uint64_t) gpu->deviceId);
|
||||
|
||||
status = D3DKMTCloseAdapter(&(D3DKMT_CLOSEADAPTER) { .hAdapter = adapter->hAdapter });
|
||||
if (NT_SUCCESS(status)) {
|
||||
FF_DEBUG("Closed adapter #%u successfully", i);
|
||||
} else {
|
||||
FF_DEBUG("Failed to close adapter #%u: %s", i, ffDebugNtStatus(status));
|
||||
}
|
||||
}
|
||||
|
||||
FF_DEBUG("GPU detection completed, found %d devices", deviceCount);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user