GPU: detects max PCI gen & link width

This commit is contained in:
Carter Li
2026-06-13 15:20:40 +08:00
committed by 李通洲
parent 55eb3c59d4
commit 4e44c0520b
22 changed files with 252 additions and 50 deletions
+1
View File
@@ -33,5 +33,6 @@ static inline const char* ffFindFileName(const char* file) {
#if _WIN32
const char* ffDebugWin32Error(DWORD errorCode);
const char* ffDebugNtStatus(NTSTATUS status);
const char* ffDebugConfigRet(unsigned long /*CONFIGRET*/ ret);
const char* ffDebugHResult(HRESULT hr);
#endif
+5
View File
@@ -2,6 +2,7 @@
#include "common/windows/nt.h"
#include <windows.h>
#include <cfgmgr32.h>
const char* ffDebugWin32Error(DWORD errorCode) {
static char buffer[512];
@@ -34,6 +35,10 @@ const char* ffDebugWin32Error(DWORD errorCode) {
return buffer;
}
const char* ffDebugConfigRet(CONFIGRET ret) {
return ffDebugWin32Error(CM_MapCrToWin32Err(ret, ERROR_INTERNAL_ERROR));
}
const char* ffDebugNtStatus(NTSTATUS status) {
return ffDebugWin32Error(RtlNtStatusToDosError(status));
}
+3
View File
@@ -26,6 +26,9 @@ extern int ADL2_Adapter_DedicatedVRAMUsage_Get(ADL_CONTEXT_HANDLE context, int i
// Function to get the ASICFamilyType from the adapter.
extern int ADL2_Adapter_ASICFamilyType_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* lpAsicTypes, int* lpValids);
// This function retrieves the chipset information for a specified adapter.
extern int ADL2_Adapter_ChipSetInfo_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLChipSetInfo* lpChipSetInfo);
// Function to retrieve current power management capabilities.
extern int ADL2_Overdrive_Caps(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iSupported, int* iEnabled, int* iVersion);
+13
View File
@@ -152,6 +152,18 @@ typedef struct _D3DKMT_QUERY_DEVICE_IDS {
D3DKMT_DEVICE_IDS DeviceIds; // out:
} D3DKMT_QUERY_DEVICE_IDS;
typedef enum _D3DKMT_PNP_KEY_TYPE {
D3DKMT_PNP_KEY_HARDWARE,
D3DKMT_PNP_KEY_SOFTWARE
} D3DKMT_PNP_KEY_TYPE;
typedef struct _D3DKMT_QUERY_PHYSICAL_ADAPTER_PNP_KEY {
UINT PhysicalAdapterIndex;
D3DKMT_PNP_KEY_TYPE PnPKeyType;
WCHAR* pDest;
UINT* pCchDest;
} D3DKMT_QUERY_PHYSICAL_ADAPTER_PNP_KEY;
typedef enum _QAI_DRIVERVERSION {
KMT_DRIVERVERSION_WDDM_1_0 = 1000, // Windows Vista
KMT_DRIVERVERSION_WDDM_1_1_PRERELEASE = 1102, // Windows Vista with prereleased Win7 features
@@ -187,6 +199,7 @@ typedef enum _KMTQUERYADAPTERINFOTYPE {
KMTQAITYPE_UMD_DRIVER_VERSION = 18,
KMTQAITYPE_NODEMETADATA = 25, // WDDM 2.0, Windows 10
KMTQAITYPE_PHYSICALADAPTERDEVICEIDS = 31,
KMTQAITYPE_PHYSICALADAPTERPNPKEY = 41, // WDDM 2.2, Windows 10 (1703)
KMTQAITYPE_QUERY_ADAPTER_UNIQUE_GUID = 60, // WDDM 2.4, Windows 10 (1803)
KMTQAITYPE_NODEPERFDATA = 61,
KMTQAITYPE_ADAPTERPERFDATA = 62,
+3
View File
@@ -7,6 +7,7 @@
#define FF_GPU_CORE_COUNT_UNSET -1
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t) -1)
#define FF_GPU_FREQUENCY_UNSET 0
#define FF_GPU_PCI_INFO_UNSET 0
#define FF_GPU_CORE_USAGE_UNSET (-DBL_MAX)
#define FF_GPU_INDEX_UNSET ((uint32_t) -1)
@@ -46,6 +47,8 @@ typedef struct FFGPUResult {
double coreUsage;
int32_t coreCount;
uint32_t frequency; // Maximum time clock frequency in MHz
uint16_t pcieGen;
uint16_t pcieLanes;
FFGPUMemory dedicated;
FFGPUMemory shared;
uint64_t deviceId;
+22
View File
@@ -52,6 +52,7 @@ struct FFAdlData {
FF_LIBRARY_SYMBOL(ADL2_Adapter_MemoryInfo2_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_DedicatedVRAMUsage_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_ASICFamilyType_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_ChipSetInfo_Get)
FF_LIBRARY_SYMBOL(ADL2_Overdrive_Caps)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_CapabilitiesX2_Get)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_SystemClocksX2_Get)
@@ -89,6 +90,7 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_MemoryInfo2_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_DedicatedVRAMUsage_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_ASICFamilyType_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_ChipSetInfo_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive_Caps)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_CapabilitiesX2_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_SystemClocksX2_Get)
@@ -233,6 +235,26 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
FF_DEBUG("Setting adapter name: %s; UDID: %s, Present: %d, Exist: %d", device->strAdapterName, device->strUDID, device->iPresent, device->iExist);
}
if (result.pcieGen || result.pcieLanes) {
ADLChipSetInfo chipSetInfo;
int status = adlData.ffADL2_Adapter_ChipSetInfo_Get(adlData.apiHandle, device->iAdapterIndex, &chipSetInfo);
FF_DEBUG("ADL2_Adapter_ChipSetInfo_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK) {
FF_DEBUG("Chipset info - Bus Type: %d, PCIe Lane Width: %d", chipSetInfo.iBusType, chipSetInfo.iMaxPCIELaneWidth);
if (result.pcieGen && chipSetInfo.iBusType >= 2) {
*result.pcieGen = (uint16_t) (chipSetInfo.iBusType - 2);
FF_DEBUG("Got PCIe Gen: %u", *result.pcieGen);
}
if (result.pcieLanes && chipSetInfo.iMaxPCIELaneWidth > 0) {
*result.pcieLanes = (uint16_t) chipSetInfo.iMaxPCIELaneWidth;
FF_DEBUG("Got PCIe Lanes: %u", *result.pcieLanes);
}
} else {
FF_DEBUG("Failed to get chipset information");
}
}
int odVersion = 0;
{
+1
View File
@@ -118,6 +118,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
IORegistryEntryGetRegistryEntryID(registryEntry, &gpu->deviceId);
ffStrbufInitStatic(&gpu->platformApi, "IOKit");
+1
View File
@@ -148,6 +148,7 @@ const char* ffGPUDetectByDrmBSD(const FFGPUOptions* options, FFlist* gpus) {
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(pciInfo.domain, pciInfo.bus, pciInfo.dev, pciInfo.func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
char driverName[64];
driverName[0] = '\0';
+2
View File
@@ -36,6 +36,8 @@ typedef struct FFGpuDriverResult {
FFGPUType* type;
uint32_t* frequency;
FFstrbuf* name;
uint16_t* pcieGen;
uint16_t* pcieLanes;
} FFGpuDriverResult;
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
+4
View File
@@ -113,6 +113,8 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
gpu->frequency = (uint32_t) (devInfo.max_engine_clock / 1000u);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->type = devInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
gpu->pcieGen = (uint16_t) devInfo.pcie_gen;
gpu->pcieLanes = (uint16_t) devInfo.pcie_num_lanes;
#define FF_VRAM_CASE(name, value) \
case value /* AMDGPU_VRAM_TYPE_ ## name */: \
ffStrbufSetStatic(&gpu->memoryType, #name); \
@@ -373,6 +375,8 @@ const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult*
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = &gpu->name,
.pcieGen = options->driverSpecific ? &gpu->pcieGen : NULL,
.pcieLanes = options->driverSpecific ? &gpu->pcieLanes : NULL,
},
soName);
}
+1
View File
@@ -130,6 +130,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(deviceId, revision, gpu);
+1
View File
@@ -37,6 +37,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(0, dev.bus, dev.device, dev.function);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(dev.device_id, dev.revision, gpu);
+14
View File
@@ -16,6 +16,7 @@ struct FFIgclData {
FF_LIBRARY_SYMBOL(ctlMemoryGetState)
FF_LIBRARY_SYMBOL(ctlEnumFrequencyDomains)
FF_LIBRARY_SYMBOL(ctlFrequencyGetProperties)
FF_LIBRARY_SYMBOL(ctlPciGetProperties)
bool inited;
ctl_api_handle_t apiHandle;
@@ -43,6 +44,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetState)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumFrequencyDomains)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlFrequencyGetProperties)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlPciGetProperties)
if (ffctlInit(&(ctl_init_args_t) {
.AppVersion = CTL_IMPL_VERSION,
@@ -227,5 +229,17 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
ffStrbufSetS(result.name, properties.name);
}
if (result.pcieGen || result.pcieLanes) {
ctl_pci_properties_t pciProps = { .Size = sizeof(pciProps), .Version = 0 };
if (igclData.ffctlPciGetProperties(device, &pciProps) == CTL_RESULT_SUCCESS) {
if (result.pcieGen && pciProps.maxSpeed.gen > 0) {
*result.pcieGen = (uint16_t) pciProps.maxSpeed.gen;
}
if (result.pcieLanes && pciProps.maxSpeed.width > 0) {
*result.pcieLanes = (uint16_t) pciProps.maxSpeed.width;
}
}
}
return NULL;
}
+31
View File
@@ -368,6 +368,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(pciDomain, pciBus, pciDevice, pciFunc);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
char drmKeyBuffer[8];
if (!drmKey) {
@@ -393,6 +394,36 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey);
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
ffStrbufAppendS(deviceDir, "/max_link_speed");
if (ffReadFileBuffer(deviceDir->chars, buffer)) {
int32_t maxLinkSpeed = (int32_t) ffStrbufToSInt(buffer, FF_GPU_PCI_INFO_UNSET);
if (maxLinkSpeed >= 64) {
gpu->pcieGen = 6;
} else if (maxLinkSpeed >= 32) {
gpu->pcieGen = 5;
} else if (maxLinkSpeed >= 16) {
gpu->pcieGen = 4;
} else if (maxLinkSpeed >= 8) {
gpu->pcieGen = 3;
} else if (maxLinkSpeed >= 5) {
gpu->pcieGen = 2;
} else if (maxLinkSpeed >= 2) { // 2.5
gpu->pcieGen = 1;
}
}
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
if (gpu->pcieGen != FF_GPU_PCI_INFO_UNSET) {
ffStrbufAppendS(deviceDir, "/max_link_width");
if (ffReadFileBuffer(deviceDir->chars, buffer)) {
int32_t maxLinkWidth = (int32_t) ffStrbufToSInt(buffer, FF_GPU_PCI_INFO_UNSET);
if (maxLinkWidth > 0 && maxLinkWidth < 255) { // kernel returns 255 if the value is unknown
gpu->pcieLanes = (uint16_t) maxLinkWidth;
}
}
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
}
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
bool ok = false;
if (drmKey && options->driverSpecific) {
+1
View File
@@ -97,6 +97,7 @@ const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpu
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
+18
View File
@@ -14,6 +14,8 @@ struct FFNvmlData {
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo)
FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates)
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxPcieLinkGeneration)
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxPcieLinkWidth)
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
FF_LIBRARY_SYMBOL(nvmlDeviceGetIndex)
FF_LIBRARY_SYMBOL(nvmlDeviceGetName)
@@ -159,6 +161,8 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxPcieLinkGeneration)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxPcieLinkWidth)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetIndex)
@@ -288,6 +292,20 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
}
}
if (result.pcieGen) {
unsigned int value;
if (nvmlData.ffnvmlDeviceGetMaxPcieLinkGeneration(device, &value) == NVML_SUCCESS) {
*result.pcieGen = (uint16_t) value;
}
}
if (result.pcieLanes) {
unsigned int value;
if (nvmlData.ffnvmlDeviceGetMaxPcieLinkWidth(device, &value) == NVML_SUCCESS) {
*result.pcieLanes = (uint16_t) value;
}
}
return NULL;
#else
+1
View File
@@ -86,6 +86,7 @@ const char* detectByPci(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpus) {
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
+1
View File
@@ -21,6 +21,7 @@ static int walkDevTree(di_node_t node, FF_A_UNUSED di_minor_t minor, FFlist* gpu
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = strtoul(di_bus_addr(node), NULL, 16);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
int* revId;
+67 -49
View File
@@ -11,31 +11,26 @@
#if _WIN32
#include "common/windows/unicode.h"
#include "common/windows/registry.h"
#include "common/mallocHelper.h"
#if FF_WIN81_COMPAT
#include "common/mallocHelper.h"
#include <windows.h>
#include <cfgmgr32.h>
#include <devguid.h>
#define INITGUID
#include <windows.h>
#include <cfgmgr32.h>
#include <devguid.h>
#include <pciprop.h>
#define GUID_DEVCLASS_DISPLAY_STRING L"{4d36e968-e325-11ce-bfc1-08002be10318}" // Found in <devguid.h>
#define GUID_DEVCLASS_DISPLAY_STRING L"{4d36e968-e325-11ce-bfc1-08002be10318}" // Found in <devguid.h>
static bool queryDeviceIdsFallback(D3DKMT_ADAPTERADDRESS adapterAddress, D3DKMT_DEVICE_IDS* outDeviceIds) {
FF_DEBUG("KMTQAITYPE_PHYSICALADAPTERDEVICEIDS failed. Attempting queryDeviceIdsFallback: bus=%u device=%u function=%u",
adapterAddress.BusNumber,
adapterAddress.DeviceNumber,
adapterAddress.FunctionNumber);
if (adapterAddress.BusNumber == -1u) {
FF_DEBUG("Invalid adapter address, cannot query device IDs");
return false;
}
static bool queryPciDeviceInfo(FFGPUResult* gpu, D3DKMT_DEVICE_IDS* outDeviceIds) {
FF_DEBUG("Query PCI device info: %08llX", gpu->deviceId);
static FFlist deviceIdsCache;
static bool initialized;
typedef struct {
uint32_t maxLinkSpeed;
uint32_t maxLinkWidth;
D3DKMT_DEVICE_IDS deviceIds;
D3DKMT_ADAPTERADDRESS adapterAddress;
uint64_t adapterAddress;
} CacheEntry;
if (!initialized) {
@@ -79,34 +74,29 @@ static bool queryDeviceIdsFallback(D3DKMT_ADAPTERADDRESS adapterAddress, D3DKMT_
continue;
}
uint32_t pciBus = 0;
CacheEntry* entry = FF_LIST_ADD(CacheEntry, deviceIdsCache);
*entry = (CacheEntry) {};
// L"PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1\\4&3674a6b9&0&0008"
if (swscanf(devId + 4, L"VEN_%x&DEV_%x&SUBSYS_%4x%4x&REV_%x", &entry->deviceIds.VendorID, &entry->deviceIds.DeviceID, &entry->deviceIds.SubSystemID, &entry->deviceIds.SubVendorID, &entry->deviceIds.RevisionID) >= 2) {
FF_DEBUG("Parsed PCI IDs - Vendor: 0x%04x, Device: 0x%04x, SubVendor: 0x%04x, SubSystem: 0x%04x, Rev: 0x%04x", entry->deviceIds.VendorID, entry->deviceIds.DeviceID, entry->deviceIds.SubVendorID, entry->deviceIds.SubSystemID, entry->deviceIds.RevisionID);
// I thought it was DXGKMDT_OPM_BUS_TYPE_PCI, but it turns out to be false
// Who TF knows what 1 actually means. It's just reported by most graphic cards
// And yeah, DXGKMDT_OPM_BUS_TYPE_PCIEXPRESS (3) exists
entry->deviceIds.BusType = 1;
} else {
FF_DEBUG("Failed to parse PCI IDs from device ID string");
deviceIdsCache.length--; // remove the cache entry since it's not valid
continue;
}
uint32_t pciBus = 0;
ULONG pciBufLen = sizeof(pciBus);
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_BUSNUMBER, NULL, &pciBus, &pciBufLen, 0) == CR_SUCCESS) {
uint32_t pciAddr = 0;
pciBufLen = sizeof(pciAddr);
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_ADDRESS, NULL, &pciAddr, &pciBufLen, 0) == CR_SUCCESS) {
CacheEntry* entry = FF_LIST_ADD(CacheEntry, deviceIdsCache);
entry->deviceIds = (D3DKMT_DEVICE_IDS) {};
// L"PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1\\4&3674a6b9&0&0008"
if (swscanf(devId + 4, L"VEN_%x&DEV_%x&SUBSYS_%4x%4x&REV_%x", &entry->deviceIds.VendorID, &entry->deviceIds.DeviceID, &entry->deviceIds.SubSystemID, &entry->deviceIds.SubVendorID, &entry->deviceIds.RevisionID) >= 2) {
FF_DEBUG("Parsed PCI IDs - Vendor: 0x%04x, Device: 0x%04x, SubVendor: 0x%04x, SubSystem: 0x%04x, Rev: 0x%04x", entry->deviceIds.VendorID, entry->deviceIds.DeviceID, entry->deviceIds.SubVendorID, entry->deviceIds.SubSystemID, entry->deviceIds.RevisionID);
// I thought it was DXGKMDT_OPM_BUS_TYPE_PCI, but it turns out to be false
// Who TF knows what 1 actually means. It's just reported by most graphic cards
// And yeah, DXGKMDT_OPM_BUS_TYPE_PCIEXPRESS (3) exists
entry->deviceIds.BusType = 1;
} else {
FF_DEBUG("Failed to parse PCI IDs from device ID string");
deviceIdsCache.length--; // remove the cache entry since it's not valid
continue;
}
entry->adapterAddress = (D3DKMT_ADAPTERADDRESS) {
.BusNumber = pciBus,
.DeviceNumber = (pciAddr >> 16) & 0xFFFF,
.FunctionNumber = pciAddr & 0xFFFF,
};
entry->adapterAddress = ffGPUPciAddr2Id(0, pciBus, (pciAddr >> 16) & 0xFFFF, pciAddr & 0xFFFF);
FF_DEBUG("Cached device IDs for PCI bus %u: vendor=0x%04x device=0x%04x", pciBus, entry->deviceIds.VendorID, entry->deviceIds.DeviceID);
} else {
FF_DEBUG("Failed to get PCI address");
@@ -114,21 +104,44 @@ static bool queryDeviceIdsFallback(D3DKMT_ADAPTERADDRESS adapterAddress, D3DKMT_
} else {
FF_DEBUG("Failed to get PCI bus number");
}
pciBufLen = sizeof(entry->maxLinkSpeed);
DEVPROPTYPE propType;
// Reports PCEe gen despite the PKEY name
CONFIGRET ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_MaxLinkSpeed, &propType, (PBYTE) &entry->maxLinkSpeed, &pciBufLen, 0);
if (ret == CR_SUCCESS) {
FF_DEBUG("PCIe GEN: %u", entry->maxLinkSpeed);
} else {
FF_DEBUG("Failed to get PCIe GEN: %s", ffDebugConfigRet(ret));
}
if (entry->maxLinkSpeed != FF_GPU_PCI_INFO_UNSET) {
pciBufLen = sizeof(entry->maxLinkWidth);
ret = CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_PciDevice_MaxLinkWidth, &propType, (PBYTE) &entry->maxLinkWidth, &pciBufLen, 0);
if (ret == CR_SUCCESS) {
FF_DEBUG("PCIe max link width: %u", entry->maxLinkWidth);
} else {
FF_DEBUG("Failed to get PCIe max link width: %s", ffDebugConfigRet(ret));
}
}
}
}
FF_LIST_FOR_EACH (CacheEntry, entry, deviceIdsCache) {
if (memcmp(&entry->adapterAddress, &adapterAddress, sizeof(adapterAddress)) == 0) {
FF_DEBUG("Cache hit for adapter address: bus=%u device=%u function=%u", adapterAddress.BusNumber, adapterAddress.DeviceNumber, adapterAddress.FunctionNumber);
*outDeviceIds = entry->deviceIds;
if (gpu->deviceId == entry->adapterAddress) {
FF_DEBUG("Cache hit for adapter address: %08llX", gpu->deviceId);
if (outDeviceIds->VendorID != -1u) {
*outDeviceIds = entry->deviceIds;
}
gpu->pcieGen = (uint16_t) entry->maxLinkSpeed;
gpu->pcieLanes = (uint16_t) entry->maxLinkWidth;
return true;
}
}
FF_DEBUG("Cache miss for adapter address: bus=%u device=%u function=%u", adapterAddress.BusNumber, adapterAddress.DeviceNumber, adapterAddress.FunctionNumber);
FF_DEBUG("Cache miss for adapter address: %08llX", gpu->deviceId);
return false;
}
#endif // FF_WIN81_COMPAT
static bool queryVendorNameViaRegistry(FFstrbuf* vendor, D3DKMT_HANDLE hAdapter) {
// `KMTQAITYPE_QUERY_ADAPTER_UNIQUE_GUID` reports the GUID value used by the adapter's registry key (DirectX and Video)
@@ -278,6 +291,7 @@ ffGPUDetectWsl2
: adapterType.HybridDiscrete
? FF_GPU_TYPE_DISCRETE
: FF_GPU_TYPE_UNKNOWN;
gpu->pcieGen = gpu->pcieLanes = FF_GPU_PCI_INFO_UNSET;
D3DKMT_DRIVERVERSION wddmVersion = KMT_DRIVERVERSION_WDDM_2_0;
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
@@ -323,11 +337,7 @@ ffGPUDetectWsl2
.pPrivateDriverData = &deviceIds,
.PrivateDriverDataSize = sizeof(deviceIds),
});
if (NT_SUCCESS(status)
#if FF_WIN81_COMPAT
|| queryDeviceIdsFallback(adapterAddress, &deviceIds.DeviceIds)
#endif
) {
if (NT_SUCCESS(status)) {
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(deviceIds.DeviceIds.VendorID));
FF_DEBUG("Adapter #%u vendor/device IDs: vendor=0x%04x device=0x%04x",
i,
@@ -338,6 +348,14 @@ ffGPUDetectWsl2
FF_DEBUG("KMTQAITYPE_PHYSICALADAPTERDEVICEIDS query failed for adapter #%u: %s", i, ffDebugNtStatus(status));
}
#if _WIN32
if (adapterAddress.BusNumber != -1u) {
if (queryPciDeviceInfo(gpu, &deviceIds.DeviceIds) && gpu->vendor.length == 0) {
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(deviceIds.DeviceIds.VendorID));
}
}
#endif
D3DKMT_UMD_DRIVER_VERSION umdDriverVersion;
status = D3DKMTQueryAdapterInfo(&(D3DKMT_QUERYADAPTERINFO) {
.hAdapter = adapter->hAdapter,
+35 -1
View File
@@ -5,6 +5,7 @@
// DOCUMENTATION REFERENCED BELOW, IN ORDER TO MAKE FASTFETCH MIT COMPLIANT.
#include <stdint.h>
#include <stdbool.h>
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv412ctl_result_t
typedef enum ctl_result_t {
@@ -73,7 +74,7 @@ typedef struct ctl_adapter_bdf_t {
} ctl_adapter_bdf_t;
#define IGCL_CTL_MAX_DEVICE_NAME_LEN 100
#define IGCL_CTL_MAX_RESERVED_SIZE 112
#define IGCL_CTL_MAX_RESERVED_SIZE 108
typedef enum ctl_adapter_properties_flag_t {
CTL_ADAPTER_PROPERTIES_FLAG_INTEGRATED = 1,
@@ -101,6 +102,7 @@ typedef struct ctl_device_adapter_properties_t {
uint16_t pci_subsys_id;
uint16_t pci_subsys_vendor_id;
ctl_adapter_bdf_t adapter_bdf;
uint32_t num_xe_cores;
char reserved[IGCL_CTL_MAX_RESERVED_SIZE];
} ctl_device_adapter_properties_t;
@@ -214,3 +216,35 @@ typedef struct ctl_freq_properties_t {
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv425ctlFrequencyGetProperties17ctl_freq_handle_tP21ctl_freq_properties_t
extern ctl_result_t ctlFrequencyGetProperties(ctl_freq_handle_t hFrequency, ctl_freq_properties_t* pProperties);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv415ctl_pci_speed_t
typedef struct ctl_pci_speed_t {
uint32_t Size;
uint8_t Version;
int32_t gen;
int32_t width;
int64_t maxBandwidth;
} ctl_pci_speed_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv417ctl_pci_address_t
typedef struct ctl_pci_address_t {
uint32_t Size;
uint8_t Version;
uint32_t domain;
uint32_t bus;
uint32_t device;
uint32_t function;
} ctl_pci_address_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv420ctl_pci_properties_t
typedef struct ctl_pci_properties_t {
uint32_t Size;
uint8_t Version;
ctl_pci_address_t address;
ctl_pci_speed_t maxSpeed;
bool resizable_bar_supported;
bool resizable_bar_enabled;
} ctl_pci_properties_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctlpcigetproperties
extern ctl_result_t ctlPciGetProperties(ctl_device_adapter_handle_t hDAhandle, ctl_pci_properties_t* pProperties);
+4
View File
@@ -142,6 +142,10 @@ extern nvmlReturn_t nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t* m
extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* numCores);
// Retrieves the maximum clock speeds for the device
extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType_t type, unsigned int* clock);
// Retrieves the maximum PCIe link generation possible with this device and system
extern nvmlReturn_t nvmlDeviceGetMaxPcieLinkGeneration(nvmlDevice_t device, unsigned int* maxLinkGen);
// Retrieves the maximum PCIe link width possible with this device and system
extern nvmlReturn_t nvmlDeviceGetMaxPcieLinkWidth (nvmlDevice_t device, unsigned int* maxLinkWidth);
// Retrieves the brand of this device
extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type);
// Retrieves the current utilization rates for the device
+23
View File
@@ -139,6 +139,11 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu
}
}
char pcieSpeed[32] = "";
if (gpu->pcieGen != FF_GPU_PCI_INFO_UNSET && gpu->pcieLanes != FF_GPU_PCI_INFO_UNSET) {
snprintf(pcieSpeed, sizeof(pcieSpeed), "PCI Gen %d x%d", gpu->pcieGen, gpu->pcieLanes);
}
FF_PRINT_FORMAT_CHECKED(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
FF_ARG(gpu->vendor, "vendor"),
FF_ARG(gpu->name, "name"),
@@ -160,6 +165,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu
FF_ARG(coreUsageNum, "core-usage-num"),
FF_ARG(coreUsageBar, "core-usage-bar"),
FF_ARG(gpu->memoryType, "memory-type"),
FF_ARG(pcieSpeed, "pcie-speed"),
}));
}
}
@@ -420,6 +426,22 @@ bool ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_
}
yyjson_mut_obj_add_uint(doc, obj, "deviceId", gpu->deviceId);
if (gpu->pcieGen != FF_GPU_PCI_INFO_UNSET || gpu->pcieLanes != FF_GPU_PCI_INFO_UNSET) {
yyjson_mut_val* pcieSpeed = yyjson_mut_obj_add_obj(doc, obj, "pcieSpeed");
if (gpu->pcieGen != FF_GPU_PCI_INFO_UNSET) {
yyjson_mut_obj_add_uint(doc, pcieSpeed, "gen", gpu->pcieGen);
} else {
yyjson_mut_obj_add_null(doc, pcieSpeed, "gen");
}
if (gpu->pcieLanes != FF_GPU_PCI_INFO_UNSET) {
yyjson_mut_obj_add_uint(doc, pcieSpeed, "lanes", gpu->pcieLanes);
} else {
yyjson_mut_obj_add_null(doc, pcieSpeed, "lanes");
}
} else {
yyjson_mut_obj_add_null(doc, obj, "pcieSpeed");
}
}
FF_LIST_FOR_EACH (FFGPUResult, gpu, gpus) {
@@ -484,5 +506,6 @@ FFModuleBaseInfo ffGPUModuleInfo = {
{ "Core usage percentage num", "core-usage-num" },
{ "Core usage percentage bar", "core-usage-bar" },
{ "Memory type (Windows only)", "memory-type" },
{ "Maximum PCIe speed in gen and lanes", "pcie-speed" },
})),
};