Chore: run clang-format

```bash
find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) ! -path "src/3rdparty/*" -print0 | xargs -0 clang-format -i
```
This commit is contained in:
李通洲
2026-03-29 09:28:49 +08:00
parent cdd4cee968
commit e0eba8ce21
690 changed files with 28093 additions and 30062 deletions
+5 -9
View File
@@ -26,11 +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);
// Function to retrieve current power management capabilities.
extern int ADL2_Overdrive_Caps(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iSupported, int* iEnabled, int* iVersion);
/////////// Overdrive 6 functions
// Function to retrieve current Overdrive and performance-related activity.
@@ -42,7 +40,6 @@ extern int ADL2_Overdrive6_Temperature_Get(ADL_CONTEXT_HANDLE context, int iAdap
// Function to retrieve the current or default Overdrive clock ranges.
extern int ADL2_Overdrive6_StateInfo_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int iStateType, ADLOD6StateInfo* lpStateInfo);
/// Overdrive N functions
// Despite the name (N means Next), this is actually Overdrive7 API
@@ -52,19 +49,18 @@ extern int ADL2_Overdrive6_StateInfo_Get(ADL_CONTEXT_HANDLE context, int iAdapte
extern int ADL2_OverdriveN_CapabilitiesX2_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLODNCapabilitiesX2* lpODCapabilities);
// Function to retrieve the current OD performance status.
extern int ADL2_OverdriveN_PerformanceStatus_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLODNPerformanceStatus *lpODPerformanceStatus);
extern int ADL2_OverdriveN_PerformanceStatus_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLODNPerformanceStatus* lpODPerformanceStatus);
// Function to retrieve the current temperature.
extern int ADL2_OverdriveN_Temperature_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int iTemperatureType, int *iTemperature);
extern int ADL2_OverdriveN_Temperature_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int iTemperatureType, int* iTemperature);
// Function to retrieve the current GPU clocks settings.
extern int ADL2_OverdriveN_SystemClocksX2_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLODNPerformanceLevelsX2 *lpODPerformanceLevels);
extern int ADL2_OverdriveN_SystemClocksX2_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLODNPerformanceLevelsX2* lpODPerformanceLevels);
/// Overdrive 8 functions
// Function to retrieve the Overdrive8 current settings.
extern int ADL2_Overdrive8_Current_Setting_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLOD8CurrentSetting *lpCurrentSetting);
extern int ADL2_Overdrive8_Current_Setting_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLOD8CurrentSetting* lpCurrentSetting);
// Function to retrieve the Overdrive8 current settings.
extern int ADL2_New_QueryPMLogData_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLPMLogDataOutput *lpDataOutput);
extern int ADL2_New_QueryPMLogData_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLPMLogDataOutput* lpDataOutput);
File diff suppressed because it is too large Load Diff
+191 -230
View File
@@ -5,11 +5,11 @@
#include <assert.h>
#if _WIN32
#include <ntdef.h>
#include <windef.h>
# include <ntdef.h>
# include <windef.h>
#else
#include <sys/ioctl.h>
#include <uchar.h>
# include <sys/ioctl.h>
# include <uchar.h>
typedef struct _LUID {
uint32_t LowPart;
@@ -38,106 +38,96 @@ typedef union {
int64_t QuadPart;
} LARGE_INTEGER;
typedef int32_t NTSTATUS; // 0 for success, -1 for failure
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
# define NT_SUCCESS(Status) ((NTSTATUS) (Status) >= 0)
#endif
#define D3DKMT_ALIGN64 __attribute__((aligned(8)))
#define MAX_ENUM_ADAPTERS 16
#define MAX_ENUM_ADAPTERS 16
typedef struct D3DKMT_HANDLE
{
typedef struct D3DKMT_HANDLE {
union {
struct {
uint32_t Instance : 6;
uint32_t Index : 24;
uint32_t Unique : 2;
uint32_t Instance : 6;
uint32_t Index : 24;
uint32_t Unique : 2;
};
uint32_t Value;
};
} D3DKMT_HANDLE;
typedef struct _D3DKMT_OPENADAPTERFROMLUID
{
LUID AdapterLuid;
D3DKMT_HANDLE hAdapter;
typedef struct _D3DKMT_OPENADAPTERFROMLUID {
LUID AdapterLuid;
D3DKMT_HANDLE hAdapter;
} D3DKMT_OPENADAPTERFROMLUID;
typedef struct _D3DKMT_ADAPTERINFO
{
D3DKMT_HANDLE hAdapter;
LUID AdapterLuid;
ULONG NumOfSources;
BOOL bPrecisePresentRegionsPreferred;
typedef struct _D3DKMT_ADAPTERINFO {
D3DKMT_HANDLE hAdapter;
LUID AdapterLuid;
ULONG NumOfSources;
BOOL bPrecisePresentRegionsPreferred;
} D3DKMT_ADAPTERINFO;
typedef struct _D3DKMT_ENUMADAPTERS2
{
ULONG NumAdapters; // in/out: On input, the count of the pAdapters array buffer. On output, the number of adapters enumerated.
D3DKMT_ADAPTERINFO* pAdapters; // out: Array of enumerated adapters containing NumAdapters elements
typedef struct _D3DKMT_ENUMADAPTERS2 {
ULONG NumAdapters; // in/out: On input, the count of the pAdapters array buffer. On output, the number of adapters enumerated.
D3DKMT_ADAPTERINFO* pAdapters; // out: Array of enumerated adapters containing NumAdapters elements
} D3DKMT_ENUMADAPTERS2;
static_assert(sizeof(D3DKMT_ENUMADAPTERS2) ==
#if SIZE_MAX == UINT64_MAX
0x10
#else
0x08
#endif
, "D3DKMT_ENUMADAPTERS2 structure size mismatch");
#if SIZE_MAX == UINT64_MAX
0x10
#else
0x08
#endif
,
"D3DKMT_ENUMADAPTERS2 structure size mismatch");
typedef struct _D3DKMT_ADAPTERREGISTRYINFO
{
WCHAR AdapterString[260];
WCHAR BiosString[260];
WCHAR DacType[260];
WCHAR ChipType[260];
typedef struct _D3DKMT_ADAPTERREGISTRYINFO {
WCHAR AdapterString[260];
WCHAR BiosString[260];
WCHAR DacType[260];
WCHAR ChipType[260];
} D3DKMT_ADAPTERREGISTRYINFO;
typedef struct _D3DKMT_CLOSEADAPTER
{
D3DKMT_HANDLE hAdapter; // in: adapter handle
typedef struct _D3DKMT_CLOSEADAPTER {
D3DKMT_HANDLE hAdapter; // in: adapter handle
} D3DKMT_CLOSEADAPTER;
typedef struct _D3DKMT_SEGMENTSIZEINFO
{
D3DKMT_ALIGN64 ULONGLONG DedicatedVideoMemorySize;
D3DKMT_ALIGN64 ULONGLONG DedicatedSystemMemorySize;
D3DKMT_ALIGN64 ULONGLONG SharedSystemMemorySize;
typedef struct _D3DKMT_SEGMENTSIZEINFO {
D3DKMT_ALIGN64 ULONGLONG DedicatedVideoMemorySize;
D3DKMT_ALIGN64 ULONGLONG DedicatedSystemMemorySize;
D3DKMT_ALIGN64 ULONGLONG SharedSystemMemorySize;
} D3DKMT_SEGMENTSIZEINFO;
typedef struct _D3DKMT_ADAPTERTYPE
{
union
{
typedef struct _D3DKMT_ADAPTERTYPE {
union {
struct
{
UINT RenderSupported : 1; // WDDM 1.2, Windows 8
UINT DisplaySupported : 1;
UINT SoftwareDevice : 1;
UINT PostDevice : 1;
UINT HybridDiscrete : 1; // WDDM 1.3, Windows 8.1
UINT HybridIntegrated : 1;
UINT IndirectDisplayDevice : 1;
UINT Paravirtualized : 1; // WDDM 2.3, Windows 10 Fall Creators Update (version 1709)
UINT ACGSupported : 1;
UINT SupportSetTimingsFromVidPn : 1;
UINT Detachable : 1;
UINT ComputeOnly : 1; // WDDM 2.6, Windows 10 May 2019 Update (Version 1903)
UINT Prototype : 1;
UINT RuntimePowerManagement : 1; // WDDM 2.9, Windows 10 Insider Preview "Iron"
UINT Reserved : 18;
UINT RenderSupported : 1; // WDDM 1.2, Windows 8
UINT DisplaySupported : 1;
UINT SoftwareDevice : 1;
UINT PostDevice : 1;
UINT HybridDiscrete : 1; // WDDM 1.3, Windows 8.1
UINT HybridIntegrated : 1;
UINT IndirectDisplayDevice : 1;
UINT Paravirtualized : 1; // WDDM 2.3, Windows 10 Fall Creators Update (version 1709)
UINT ACGSupported : 1;
UINT SupportSetTimingsFromVidPn : 1;
UINT Detachable : 1;
UINT ComputeOnly : 1; // WDDM 2.6, Windows 10 May 2019 Update (Version 1903)
UINT Prototype : 1;
UINT RuntimePowerManagement : 1; // WDDM 2.9, Windows 10 Insider Preview "Iron"
UINT Reserved : 18;
};
UINT Value;
};
} D3DKMT_ADAPTERTYPE;
typedef struct _D3DKMT_ADAPTERADDRESS
{
UINT BusNumber; // Bus number on which the physical device is located.
UINT DeviceNumber; // Index of the physical device on the bus.
UINT FunctionNumber; // Function number of the adapter on the physical device.
typedef struct _D3DKMT_ADAPTERADDRESS {
UINT BusNumber; // Bus number on which the physical device is located.
UINT DeviceNumber; // Index of the physical device on the bus.
UINT FunctionNumber; // Function number of the adapter on the physical device.
} D3DKMT_ADAPTERADDRESS;
typedef struct _D3DKMT_DEVICE_IDS
{
typedef struct _D3DKMT_DEVICE_IDS {
UINT VendorID;
UINT DeviceID;
UINT SubVendorID;
@@ -146,160 +136,144 @@ typedef struct _D3DKMT_DEVICE_IDS
UINT BusType;
} D3DKMT_DEVICE_IDS;
typedef struct _D3DKMT_UMD_DRIVER_VERSION
{
typedef struct _D3DKMT_UMD_DRIVER_VERSION {
D3DKMT_ALIGN64 LARGE_INTEGER DriverVersion;
} D3DKMT_UMD_DRIVER_VERSION;
typedef struct _D3DKMT_QUERY_DEVICE_IDS
{
UINT PhysicalAdapterIndex; // in:
D3DKMT_DEVICE_IDS DeviceIds; // out:
typedef struct _D3DKMT_QUERY_DEVICE_IDS {
UINT PhysicalAdapterIndex; // in:
D3DKMT_DEVICE_IDS DeviceIds; // out:
} D3DKMT_QUERY_DEVICE_IDS;
typedef enum _QAI_DRIVERVERSION
{
KMT_DRIVERVERSION_WDDM_1_0 = 1000, // Windows Vista
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
KMT_DRIVERVERSION_WDDM_1_1 = 1105, // Windows 7
KMT_DRIVERVERSION_WDDM_1_2 = 1200, // Windows 8
KMT_DRIVERVERSION_WDDM_1_3 = 1300, // Windows 8.1
KMT_DRIVERVERSION_WDDM_2_0 = 2000, // Windows 10
KMT_DRIVERVERSION_WDDM_2_1 = 2100, // Windows 10 (1607)
KMT_DRIVERVERSION_WDDM_2_2 = 2200, // Windows 10 (1703)
KMT_DRIVERVERSION_WDDM_2_3 = 2300, // Windows 10 (1709)
KMT_DRIVERVERSION_WDDM_2_4 = 2400, // Windows 10 (1803)
KMT_DRIVERVERSION_WDDM_2_5 = 2500, // Windows 10 (1809)
KMT_DRIVERVERSION_WDDM_2_6 = 2600, // Windows 10 (1903)
KMT_DRIVERVERSION_WDDM_2_7 = 2700, // Windows 10 (2004)
KMT_DRIVERVERSION_WDDM_2_8 = 2800, // Windows 11 Insider Preview Manganese
KMT_DRIVERVERSION_WDDM_2_9 = 2900, // Windows 11 Insider Preview Iron
KMT_DRIVERVERSION_WDDM_3_0 = 3000, // Windows 11 (21H2)
KMT_DRIVERVERSION_WDDM_3_1 = 3100, // Windows 11 (22H2)
KMT_DRIVERVERSION_WDDM_3_2 = 3200, // Windows 11 (24H2)
KMT_DRIVERVERSION_WDDM_1_1 = 1105, // Windows 7
KMT_DRIVERVERSION_WDDM_1_2 = 1200, // Windows 8
KMT_DRIVERVERSION_WDDM_1_3 = 1300, // Windows 8.1
KMT_DRIVERVERSION_WDDM_2_0 = 2000, // Windows 10
KMT_DRIVERVERSION_WDDM_2_1 = 2100, // Windows 10 (1607)
KMT_DRIVERVERSION_WDDM_2_2 = 2200, // Windows 10 (1703)
KMT_DRIVERVERSION_WDDM_2_3 = 2300, // Windows 10 (1709)
KMT_DRIVERVERSION_WDDM_2_4 = 2400, // Windows 10 (1803)
KMT_DRIVERVERSION_WDDM_2_5 = 2500, // Windows 10 (1809)
KMT_DRIVERVERSION_WDDM_2_6 = 2600, // Windows 10 (1903)
KMT_DRIVERVERSION_WDDM_2_7 = 2700, // Windows 10 (2004)
KMT_DRIVERVERSION_WDDM_2_8 = 2800, // Windows 11 Insider Preview Manganese
KMT_DRIVERVERSION_WDDM_2_9 = 2900, // Windows 11 Insider Preview Iron
KMT_DRIVERVERSION_WDDM_3_0 = 3000, // Windows 11 (21H2)
KMT_DRIVERVERSION_WDDM_3_1 = 3100, // Windows 11 (22H2)
KMT_DRIVERVERSION_WDDM_3_2 = 3200, // Windows 11 (24H2)
} D3DKMT_DRIVERVERSION;
typedef struct _D3DKMT_QUERY_ADAPTER_UNIQUE_GUID
{
typedef struct _D3DKMT_QUERY_ADAPTER_UNIQUE_GUID {
WCHAR AdapterUniqueGUID[40];
} D3DKMT_QUERY_ADAPTER_UNIQUE_GUID;
typedef enum _KMTQUERYADAPTERINFOTYPE
{
KMTQAITYPE_GETSEGMENTSIZE = 3,
KMTQAITYPE_ADAPTERGUID = 4,
KMTQAITYPE_ADAPTERADDRESS = 6,
KMTQAITYPE_ADAPTERREGISTRYINFO = 8,
KMTQAITYPE_DRIVERVERSION = 13,
KMTQAITYPE_ADAPTERTYPE = 15, // WDDM 1.2, Windows 8
KMTQAITYPE_UMD_DRIVER_VERSION = 18,
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)
typedef enum _KMTQUERYADAPTERINFOTYPE {
KMTQAITYPE_GETSEGMENTSIZE = 3,
KMTQAITYPE_ADAPTERGUID = 4,
KMTQAITYPE_ADAPTERADDRESS = 6,
KMTQAITYPE_ADAPTERREGISTRYINFO = 8,
KMTQAITYPE_DRIVERVERSION = 13,
KMTQAITYPE_ADAPTERTYPE = 15, // WDDM 1.2, Windows 8
KMTQAITYPE_UMD_DRIVER_VERSION = 18,
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)
} KMTQUERYADAPTERINFOTYPE;
typedef struct _D3DKMT_QUERYADAPTERINFO
{
D3DKMT_HANDLE hAdapter;
typedef struct _D3DKMT_QUERYADAPTERINFO {
D3DKMT_HANDLE hAdapter;
KMTQUERYADAPTERINFOTYPE Type;
VOID* pPrivateDriverData;
UINT PrivateDriverDataSize;
VOID* pPrivateDriverData;
UINT PrivateDriverDataSize;
} D3DKMT_QUERYADAPTERINFO;
#define D3DKMT_MAX_SEGMENT_COUNT 32
typedef enum _D3DKMT_MEMORY_SEGMENT_GROUP
{
typedef enum _D3DKMT_MEMORY_SEGMENT_GROUP {
D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL = 0,
D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL = 1
} 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,
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
{
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER {
ULONG PhysicalAdapterIndex;
} D3DKMT_QUERYSTATISTICS_QUERY_PHYSICAL_ADAPTER;
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_NODE2
{
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
D3DKMT_ALIGN64 ULONGLONG MaxMemoryFrequency; // out: Max memory clock frequency
D3DKMT_ALIGN64 ULONGLONG MaxMemoryFrequencyOC; // out: Clock frequency of the memory while overclocked in hertz.
D3DKMT_ALIGN64 ULONGLONG MemoryBandwidth; // out: Amount of memory transferred in bytes
D3DKMT_ALIGN64 ULONGLONG PCIEBandwidth; // out: Amount of memory transferred over PCI-E in bytes
ULONG FanRPM; // out: Fan rpm
ULONG Power; // out: Power draw of the adapter in tenths of a percentage
ULONG Temperature; // out: Temperature in deci-Celsius 1 = 0.1C
UCHAR PowerStateOverride; // out: Overrides dxgkrnls power view of linked adapters.
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
D3DKMT_ALIGN64 ULONGLONG MaxMemoryFrequency; // out: Max memory clock frequency
D3DKMT_ALIGN64 ULONGLONG MaxMemoryFrequencyOC; // out: Clock frequency of the memory while overclocked in hertz.
D3DKMT_ALIGN64 ULONGLONG MemoryBandwidth; // out: Amount of memory transferred in bytes
D3DKMT_ALIGN64 ULONGLONG PCIEBandwidth; // out: Amount of memory transferred over PCI-E in bytes
ULONG FanRPM; // out: Fan rpm
ULONG Power; // out: Power draw of the adapter in tenths of a percentage
ULONG Temperature; // out: Temperature in deci-Celsius 1 = 0.1C
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.
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.
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;
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_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
D3DKMT_ALIGN64 ULONGLONG Frequency; // out: Clock frequency of the engine in hertz
D3DKMT_ALIGN64 ULONGLONG MaxFrequency; // out: Max engine clock frequency
D3DKMT_ALIGN64 ULONGLONG MaxFrequencyOC;// out: Max engine over clock frequency
ULONG Voltage; // out: Voltage of the engine in milli volts mV
ULONG VoltageMax; // out: Max voltage levels in milli volts.
ULONG VoltageMaxOC; // out: Max voltage level while overclocked in milli volts.
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
D3DKMT_ALIGN64 ULONGLONG Frequency; // out: Clock frequency of the engine in hertz
D3DKMT_ALIGN64 ULONGLONG MaxFrequency; // out: Max engine clock frequency
D3DKMT_ALIGN64 ULONGLONG MaxFrequencyOC; // out: Max engine over clock frequency
ULONG Voltage; // out: Voltage of the engine in milli volts mV
ULONG VoltageMax; // out: Max voltage levels in milli volts.
ULONG VoltageMaxOC; // out: Max voltage level while overclocked in milli volts.
// WDDM 2.5
D3DKMT_ALIGN64 ULONGLONG MaxTransitionLatency; // out: Max transition latency to change the frequency in 100 nanoseconds
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_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
{
typedef struct _D3DKMT_QUERYSTATISTICS_MEMORY_USAGE {
D3DKMT_ALIGN64 UINT64 AllocatedBytes;
D3DKMT_ALIGN64 UINT64 FreeBytes;
D3DKMT_ALIGN64 UINT64 ZeroBytes;
@@ -307,45 +281,41 @@ typedef struct _D3DKMT_QUERYSTATISTICS_MEMORY_USAGE
D3DKMT_ALIGN64 UINT64 StandbyBytes;
} D3DKMT_QUERYSTATISTICS_MEMORY_USAGE;
typedef union _D3DKMT_QUERYSTATISTICS_RESULT
{
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;
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT_GROUP_USAGE
{
typedef struct _D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT_GROUP_USAGE {
UINT16 PhysicalAdapterIndex;
UINT16 SegmentGroup; // D3DKMT_MEMORY_SEGMENT_GROUP
} D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT_GROUP_USAGE;
typedef struct _D3DKMT_QUERYSTATISTICS
{
D3DKMT_QUERYSTATISTICS_TYPE Type; // in: type of data requested
LUID AdapterLuid; // in: adapter to get export / statistics from
HANDLE* hProcess; // in: process to get statistics for, if required for this query type
typedef struct _D3DKMT_QUERYSTATISTICS {
D3DKMT_QUERYSTATISTICS_TYPE Type; // in: type of data requested
LUID AdapterLuid; // in: adapter to get export / statistics from
HANDLE* hProcess; // in: process to get statistics for, if required for this query type
D3DKMT_QUERYSTATISTICS_RESULT QueryResult; // out: requested data
union
{
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) ==
#if SIZE_MAX == UINT64_MAX
0x328
#else
0x320
#endif
, "D3DKMT_QUERYSTATISTICS structure size mismatch");
#if SIZE_MAX == UINT64_MAX
0x328
#else
0x320
#endif
,
"D3DKMT_QUERYSTATISTICS structure size mismatch");
#define DXGK_MAX_METADATA_NAME_LENGTH 32
typedef enum
{
typedef enum {
DXGK_ENGINE_TYPE_OTHER,
DXGK_ENGINE_TYPE_3D,
DXGK_ENGINE_TYPE_VIDEO_DECODE,
@@ -358,38 +328,34 @@ typedef enum
DXGK_ENGINE_TYPE_VIDEO_CODEC,
DXGK_ENGINE_TYPE_MAX
} DXGK_ENGINE_TYPE;
typedef struct _DXGK_NODEMETADATA_FLAGS
{
union
{
typedef struct _DXGK_NODEMETADATA_FLAGS {
union {
struct
{
UINT ContextSchedulingSupported : 1; // WDDM 2.2
UINT RingBufferFenceRelease : 1; // WDDM 2.5
UINT SupportTrackedWorkload : 1;
UINT UserModeSubmission : 1;
UINT SupportBuildTestCommandBuffer : 1; // WDDM 3.2
UINT Reserved : 11;
UINT MaxInFlightHwQueueBuffers : 16;
UINT ContextSchedulingSupported : 1; // WDDM 2.2
UINT RingBufferFenceRelease : 1; // WDDM 2.5
UINT SupportTrackedWorkload : 1;
UINT UserModeSubmission : 1;
UINT SupportBuildTestCommandBuffer : 1; // WDDM 3.2
UINT Reserved : 11;
UINT MaxInFlightHwQueueBuffers : 16;
};
UINT32 Value;
};
} DXGK_NODEMETADATA_FLAGS;
typedef struct _DXGK_NODEMETADATA
{
typedef struct _DXGK_NODEMETADATA {
DXGK_ENGINE_TYPE EngineType;
WCHAR FriendlyName[DXGK_MAX_METADATA_NAME_LENGTH];
WCHAR FriendlyName[DXGK_MAX_METADATA_NAME_LENGTH];
DXGK_NODEMETADATA_FLAGS Flags; // WDDM 2.2
BOOLEAN GpuMmuSupported; // WDDM 2.0 ???
BOOLEAN IoMmuSupported;
} __attribute__((packed)) DXGK_NODEMETADATA;
BOOLEAN GpuMmuSupported; // WDDM 2.0 ???
BOOLEAN IoMmuSupported;
} __attribute__((packed)) DXGK_NODEMETADATA;
typedef struct _D3DKMT_NODEMETADATA
{
UINT NodeOrdinalAndAdapterIndex; // WDDMv2: High word is physical adapter index, low word is node ordinal
typedef struct _D3DKMT_NODEMETADATA {
UINT NodeOrdinalAndAdapterIndex; // WDDMv2: High word is physical adapter index, low word is node ordinal
DXGK_NODEMETADATA NodeData;
} __attribute__((packed)) D3DKMT_NODEMETADATA;
} __attribute__((packed)) D3DKMT_NODEMETADATA;
static_assert(sizeof(D3DKMT_NODEMETADATA) == 0x4E, "D3DKMT_NODEMETADATA structure size mismatch");
// Functions
@@ -405,34 +371,29 @@ EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTQueryStatistics(_In_ CONST D3DKM
#else
// Ref: https://github.com/microsoft/WSL2-Linux-Kernel/blob/linux-msft-wsl-6.6.y/include/uapi/misc/d3dkmthk.h
#define LX_DXOPENADAPTERFROMLUID _IOWR(0x47, 0x01, D3DKMT_OPENADAPTERFROMLUID)
#define LX_DXQUERYADAPTERINFO _IOWR(0x47, 0x09, D3DKMT_QUERYADAPTERINFO)
#define LX_DXENUMADAPTERS2 _IOWR(0x47, 0x14, D3DKMT_ENUMADAPTERS2)
#define LX_DXCLOSEADAPTER _IOWR(0x47, 0x15, D3DKMT_CLOSEADAPTER)
#define LX_DXQUERYSTATISTICS _IOWR(0x47, 0x43, D3DKMT_QUERYSTATISTICS)
# define LX_DXOPENADAPTERFROMLUID _IOWR(0x47, 0x01, D3DKMT_OPENADAPTERFROMLUID)
# define LX_DXQUERYADAPTERINFO _IOWR(0x47, 0x09, D3DKMT_QUERYADAPTERINFO)
# define LX_DXENUMADAPTERS2 _IOWR(0x47, 0x14, D3DKMT_ENUMADAPTERS2)
# define LX_DXCLOSEADAPTER _IOWR(0x47, 0x15, D3DKMT_CLOSEADAPTER)
# define LX_DXQUERYSTATISTICS _IOWR(0x47, 0x43, D3DKMT_QUERYSTATISTICS)
static inline NTSTATUS D3DKMTOpenAdapterFromLuid(int dxgfd, const D3DKMT_OPENADAPTERFROMLUID* params)
{
static inline NTSTATUS D3DKMTOpenAdapterFromLuid(int dxgfd, const D3DKMT_OPENADAPTERFROMLUID* params) {
return ioctl(dxgfd, LX_DXOPENADAPTERFROMLUID, params);
}
static inline NTSTATUS D3DKMTQueryAdapterInfo(int dxgfd, const D3DKMT_QUERYADAPTERINFO* params)
{
static inline NTSTATUS D3DKMTQueryAdapterInfo(int dxgfd, const D3DKMT_QUERYADAPTERINFO* params) {
return ioctl(dxgfd, LX_DXQUERYADAPTERINFO, params);
}
static inline NTSTATUS D3DKMTCloseAdapter(int dxgfd, const D3DKMT_CLOSEADAPTER* params)
{
static inline NTSTATUS D3DKMTCloseAdapter(int dxgfd, const D3DKMT_CLOSEADAPTER* params) {
return ioctl(dxgfd, LX_DXCLOSEADAPTER, params);
}
static inline NTSTATUS D3DKMTEnumAdapters2(int dxgfd, D3DKMT_ENUMADAPTERS2* params)
{
static inline NTSTATUS D3DKMTEnumAdapters2(int dxgfd, D3DKMT_ENUMADAPTERS2* params) {
return ioctl(dxgfd, LX_DXENUMADAPTERS2, params);
}
static inline NTSTATUS D3DKMTQueryStatistics(int dxgfd, const D3DKMT_QUERYSTATISTICS* params)
{
static inline NTSTATUS D3DKMTQueryStatistics(int dxgfd, const D3DKMT_QUERYSTATISTICS* params) {
return ioctl(dxgfd, LX_DXQUERYSTATISTICS, params);
}
+67 -57
View File
@@ -23,34 +23,57 @@ const char* FF_GPU_VENDOR_NAME_JINGJIA_MICRO = "Jingjia Micro";
const char* FF_GPU_VENDOR_NAME_HUAWEI = "Huawei";
const char* FF_GPU_VENDOR_NAME_ZHAOXIN = "Zhaoxin";
const char* ffGPUGetVendorString(unsigned vendorId)
{
const char* ffGPUGetVendorString(unsigned vendorId) {
// https://devicehunt.com/all-pci-vendors
switch (vendorId)
{
case 0x106b: return FF_GPU_VENDOR_NAME_APPLE;
case 0x1002: case 0x1022: case 0x1dd8: return FF_GPU_VENDOR_NAME_AMD;
case 0x8086: case 0x8087: case 0x03e7: return FF_GPU_VENDOR_NAME_INTEL;
case 0x0955: case 0x10de: case 0x12d2: return FF_GPU_VENDOR_NAME_NVIDIA;
case 0x1ed5: return FF_GPU_VENDOR_NAME_MTHREADS;
case 0x17cb: case 0x5143: return FF_GPU_VENDOR_NAME_QUALCOMM;
case 0x14c3: return FF_GPU_VENDOR_NAME_MTK;
case 0x15ad: return FF_GPU_VENDOR_NAME_VMWARE;
case 0x1af4: return FF_GPU_VENDOR_NAME_REDHAT;
case 0x1ab8: return FF_GPU_VENDOR_NAME_PARALLEL;
case 0x1414: return FF_GPU_VENDOR_NAME_MICROSOFT;
case 0x108e: return FF_GPU_VENDOR_NAME_ORACLE;
case 0x182f: case 0x14e4: return FF_GPU_VENDOR_NAME_BROADCOM;
case 0x0014: return FF_GPU_VENDOR_NAME_LOONGSON;
case 0x0731: return FF_GPU_VENDOR_NAME_JINGJIA_MICRO;
case 0x19e5: return FF_GPU_VENDOR_NAME_HUAWEI;
case 0x1d17: return FF_GPU_VENDOR_NAME_ZHAOXIN;
default: return NULL;
switch (vendorId) {
case 0x106b:
return FF_GPU_VENDOR_NAME_APPLE;
case 0x1002:
case 0x1022:
case 0x1dd8:
return FF_GPU_VENDOR_NAME_AMD;
case 0x8086:
case 0x8087:
case 0x03e7:
return FF_GPU_VENDOR_NAME_INTEL;
case 0x0955:
case 0x10de:
case 0x12d2:
return FF_GPU_VENDOR_NAME_NVIDIA;
case 0x1ed5:
return FF_GPU_VENDOR_NAME_MTHREADS;
case 0x17cb:
case 0x5143:
return FF_GPU_VENDOR_NAME_QUALCOMM;
case 0x14c3:
return FF_GPU_VENDOR_NAME_MTK;
case 0x15ad:
return FF_GPU_VENDOR_NAME_VMWARE;
case 0x1af4:
return FF_GPU_VENDOR_NAME_REDHAT;
case 0x1ab8:
return FF_GPU_VENDOR_NAME_PARALLEL;
case 0x1414:
return FF_GPU_VENDOR_NAME_MICROSOFT;
case 0x108e:
return FF_GPU_VENDOR_NAME_ORACLE;
case 0x182f:
case 0x14e4:
return FF_GPU_VENDOR_NAME_BROADCOM;
case 0x0014:
return FF_GPU_VENDOR_NAME_LOONGSON;
case 0x0731:
return FF_GPU_VENDOR_NAME_JINGJIA_MICRO;
case 0x19e5:
return FF_GPU_VENDOR_NAME_HUAWEI;
case 0x1d17:
return FF_GPU_VENDOR_NAME_ZHAOXIN;
default:
return NULL;
}
}
const char* detectByOpenGL(FFlist* gpus)
{
const char* detectByOpenGL(FFlist* gpus) {
FF_DEBUG("Starting OpenGL GPU detection fallback");
FFOpenGLResult result;
@@ -65,8 +88,7 @@ const char* detectByOpenGL(FFlist* gpus)
const char* error = ffDetectOpenGL(&options, &result);
FF_DEBUG("OpenGL detection returns: %s", error ?: "success");
if (!error)
{
if (!error) {
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
gpu->type = FF_GPU_TYPE_UNKNOWN;
ffStrbufInitMove(&gpu->vendor, &result.vendor);
@@ -79,7 +101,7 @@ const char* detectByOpenGL(FFlist* gpus)
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->dedicated = gpu->shared = (FFGPUMemory){0, 0};
gpu->dedicated = gpu->shared = (FFGPUMemory) {0, 0};
gpu->deviceId = 0;
FF_DEBUG("OpenGL reported renderer='%s', vendor='%s', version='%s'",
@@ -87,25 +109,23 @@ const char* detectByOpenGL(FFlist* gpus)
gpu->vendor.chars,
result.version.chars);
if (ffStrbufContainS(&gpu->name, "Apple"))
{
if (ffStrbufContainS(&gpu->name, "Apple")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
gpu->type = FF_GPU_TYPE_INTEGRATED;
}
else if (ffStrbufContainS(&gpu->name, "Intel"))
} else if (ffStrbufContainS(&gpu->name, "Intel")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI"))
} else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if (ffStrbufContainS(&gpu->name, "NVIDIA"))
} else if (ffStrbufContainS(&gpu->name, "NVIDIA")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
else if (ffStrbufContainS(&gpu->name, "MTT"))
} else if (ffStrbufContainS(&gpu->name, "MTT")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS);
}
FF_DEBUG("OpenGL fallback produced GPU: name='%s', vendor='%s', type=%u",
gpu->name.chars,
gpu->vendor.chars,
gpu->type);
}
ffStrbufDestroy(&result.version);
@@ -116,16 +136,13 @@ const char* detectByOpenGL(FFlist* gpus)
return error;
}
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result)
{
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) {
FF_DEBUG("Starting GPU detection with method=%d", (int) options->detectionMethod);
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_PCI)
{
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_PCI) {
FF_DEBUG("Trying PCI/native GPU detection");
const char* error = ffDetectGPUImpl(options, result);
if (!error && result->length > 0)
{
if (!error && result->length > 0) {
FF_DEBUG("PCI/native GPU detection succeeded with %u GPU(s)", result->length);
return NULL;
}
@@ -134,24 +151,21 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result)
error ?: "none",
result->length);
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_VULKAN)
{
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_VULKAN) {
FF_DEBUG("Trying Vulkan GPU detection fallback");
FFVulkanResult* vulkan = ffDetectVulkan();
if (!vulkan->error && vulkan->gpus.length > 0)
{
if (!vulkan->error && vulkan->gpus.length > 0) {
FF_DEBUG("Vulkan detection succeeded with %u GPU(s)", vulkan->gpus.length);
ffListDestroy(result);
ffListInitMove(result, &vulkan->gpus);
#ifdef __ANDROID__
#ifdef __ANDROID__
double ffGPUDetectTempFromTZ(void);
if (options->temp && result->length == 1)
{
if (options->temp && result->length == 1) {
FF_DEBUG("Applying Android thermal-zone temperature to single Vulkan GPU");
FF_LIST_GET(FFGPUResult, *result, 0)->temperature = ffGPUDetectTempFromTZ();
}
#endif
#endif
return NULL;
}
@@ -160,12 +174,10 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result)
vulkan->error ?: "none",
vulkan->gpus.length);
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENCL)
{
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENCL) {
FF_DEBUG("Trying OpenCL GPU detection fallback");
FFOpenCLResult* opencl = ffDetectOpenCL();
if (!opencl->error && opencl->gpus.length > 0)
{
if (!opencl->error && opencl->gpus.length > 0) {
FF_DEBUG("OpenCL detection succeeded with %u GPU(s)", opencl->gpus.length);
ffListDestroy(result);
ffListInitMove(result, &opencl->gpus);
@@ -176,12 +188,10 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result)
opencl->error ?: "none",
opencl->gpus.length);
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENGL)
{
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENGL) {
FF_DEBUG("Trying OpenGL GPU detection fallback");
const char* error = detectByOpenGL(result);
if (error == NULL)
{
if (error == NULL) {
FF_DEBUG("OpenGL fallback succeeded with %u GPU(s)", result->length);
return NULL;
}
+9 -14
View File
@@ -5,10 +5,10 @@
#define FF_GPU_TEMP_UNSET (-DBL_MAX)
#define FF_GPU_CORE_COUNT_UNSET -1
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1)
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t) -1)
#define FF_GPU_FREQUENCY_UNSET 0
#define FF_GPU_CORE_USAGE_UNSET (-DBL_MAX)
#define FF_GPU_INDEX_UNSET ((uint32_t)-1)
#define FF_GPU_INDEX_UNSET ((uint32_t) -1)
extern const char* FF_GPU_VENDOR_NAME_APPLE;
extern const char* FF_GPU_VENDOR_NAME_AMD;
@@ -28,14 +28,12 @@ extern const char* FF_GPU_VENDOR_NAME_JINGJIA_MICRO;
extern const char* FF_GPU_VENDOR_NAME_HUAWEI;
extern const char* FF_GPU_VENDOR_NAME_ZHAOXIN;
typedef struct FFGPUMemory
{
typedef struct FFGPUMemory {
uint64_t total;
uint64_t used;
} FFGPUMemory;
typedef struct FFGPUResult
{
typedef struct FFGPUResult {
uint32_t index;
FFGPUType type;
FFstrbuf vendor;
@@ -57,8 +55,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
const char* ffGPUGetVendorString(unsigned vendorId);
typedef struct FFGpuDriverPciBusId
{
typedef struct FFGpuDriverPciBusId {
uint32_t domain;
uint32_t bus;
uint32_t device;
@@ -69,25 +66,23 @@ typedef struct FFGpuDriverPciBusId
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu);
#if FF_HAVE_DRM
# if FF_HAVE_DRM
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd);
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd);
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd);
const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd);
#endif // FF_HAVE_DRM
# endif // FF_HAVE_DRM
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId);
#endif // defined(XXX)
static inline uint64_t ffGPUPciAddr2Id(uint64_t domain, uint64_t bus, uint64_t device, uint64_t function)
{
static inline uint64_t ffGPUPciAddr2Id(uint64_t domain, uint64_t bus, uint64_t device, uint64_t function) {
return (domain << 16) | (bus << 8) | (device << 3) | function;
}
static inline uint64_t ffGPUGeneral2Id(uint64_t originalId)
{
static inline uint64_t ffGPUGeneral2Id(uint64_t originalId) {
// Note: originalId may already have the MSB set
return (1ULL << 63) | originalId;
}
+120 -186
View File
@@ -8,7 +8,9 @@
// Helper function to convert ADL status code to string
FF_MAYBE_UNUSED static const char* ffAdlStatusToString(int status) {
switch (status) {
#define FF_ADL_STATUS_CASE(name) case name: return #name;
#define FF_ADL_STATUS_CASE(name) \
case name: \
return #name;
FF_ADL_STATUS_CASE(ADL_OK)
FF_ADL_STATUS_CASE(ADL_OK_WARNING)
FF_ADL_STATUS_CASE(ADL_OK_MODE_CHANGE)
@@ -32,14 +34,14 @@ FF_MAYBE_UNUSED static const char* ffAdlStatusToString(int status) {
FF_ADL_STATUS_CASE(ADL_ERR_NO_ADMINISTRATOR_PRIVILEGES)
FF_ADL_STATUS_CASE(ADL_ERR_FEATURESYNC_NOT_STARTED)
FF_ADL_STATUS_CASE(ADL_ERR_INVALID_POWER_STATE)
#undef FF_ADL_STATUS_CASE
default: return "Unknown ADL error";
#undef FF_ADL_STATUS_CASE
default:
return "Unknown ADL error";
}
}
// Memory allocation function
static void* __attribute__((__stdcall__)) ffAdlMainMemoryAlloc(int iSize)
{
static void* __attribute__((__stdcall__)) ffAdlMainMemoryAlloc(int iSize) {
return malloc((size_t) iSize);
}
@@ -65,25 +67,21 @@ struct FFAdlData {
ADL_CONTEXT_HANDLE apiHandle;
} adlData;
static void shutdownAdl()
{
if (adlData.apiHandle)
{
static void shutdownAdl() {
if (adlData.apiHandle) {
FF_DEBUG("Destroying ADL context");
adlData.ffADL2_Main_Control_Destroy(adlData.apiHandle);
adlData.apiHandle = NULL;
}
}
const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName)
{
const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) {
FF_DEBUG("Attempting to detect AMD GPU info using '%s'", soName);
if (!adlData.inited)
{
if (!adlData.inited) {
adlData.inited = true;
FF_DEBUG("Initializing ADL library");
FF_LIBRARY_LOAD(atiadl, "dlopen atiadlxx failed", soName , 1);
FF_LIBRARY_LOAD(atiadl, "dlopen atiadlxx failed", soName, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(atiadl, ADL2_Main_Control_Create)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Main_Control_Destroy)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_AdapterInfoX3_Get)
@@ -105,16 +103,16 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
int result = ffADL2_Main_Control_Create(ffAdlMainMemoryAlloc, 1 /*iEnumConnectedAdapters*/, &adlData.apiHandle);
FF_DEBUG("ADL2_Main_Control_Create returned %s (%d)", ffAdlStatusToString(result), result);
if (result != ADL_OK)
if (result != ADL_OK) {
return "ffADL2_Main_Control_Create() failed";
}
atexit(shutdownAdl);
atiadl = NULL; // don't close atiadl
FF_DEBUG("ADL initialization complete");
}
if (!adlData.apiHandle)
{
if (!adlData.apiHandle) {
FF_DEBUG("ADL context not initialized");
return "ffADL2_Main_Control_Create() failed";
}
@@ -124,30 +122,29 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
int adapterResult = adlData.ffADL2_Adapter_AdapterInfoX3_Get(adlData.apiHandle, -1, &numDevices, &devices);
FF_DEBUG("ADL2_Adapter_AdapterInfoX3_Get returned %s (%d)", ffAdlStatusToString(adapterResult), adapterResult);
if (adapterResult == ADL_OK)
{
if (adapterResult == ADL_OK) {
FF_DEBUG("found %d adapters", numDevices);
}
else
{
} else {
FF_DEBUG("ffADL2_Adapter_AdapterInfoX3_Get() failed");
return "ffADL2_Adapter_AdapterInfoX3_Get() failed";
}
const AdapterInfo* device = NULL;
for (int iDev = 0; iDev < numDevices; iDev++)
{
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
{
for (int iDev = 0; iDev < numDevices; iDev++) {
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) {
FF_DEBUG("Checking device %d: bus=%d, device=%d, func=%d against requested bus=%u, device=%u, func=%u",
iDev, devices[iDev].iBusNumber, devices[iDev].iDeviceNumber, devices[iDev].iFunctionNumber,
cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
iDev,
devices[iDev].iBusNumber,
devices[iDev].iDeviceNumber,
devices[iDev].iFunctionNumber,
cond->pciBusId.bus,
cond->pciBusId.device,
cond->pciBusId.func);
if (
cond->pciBusId.bus == (uint32_t) devices[iDev].iBusNumber &&
cond->pciBusId.device == (uint32_t) devices[iDev].iDeviceNumber &&
cond->pciBusId.func == (uint32_t) devices[iDev].iFunctionNumber)
{
cond->pciBusId.func == (uint32_t) devices[iDev].iFunctionNumber) {
device = &devices[iDev];
FF_DEBUG("Found matching device: %s (index: %d)", device->strAdapterName, device->iAdapterIndex);
break;
@@ -155,36 +152,32 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
}
}
if (!device)
{
if (!device) {
FF_DEBUG("Device not found");
return "Device not found";
}
if (result.coreCount)
{
if (result.coreCount) {
ADLGraphicCoreInfo coreInfo;
int status = adlData.ffADL2_Adapter_Graphic_Core_Info_Get(adlData.apiHandle, device->iAdapterIndex, &coreInfo);
FF_DEBUG("ADL2_Adapter_Graphic_Core_Info_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (status == ADL_OK) {
FF_DEBUG("Core info - NumCUs: %d, NumPEsPerCU: %d", coreInfo.iNumCUs, coreInfo.iNumPEsPerCU);
*result.coreCount = (uint32_t) coreInfo.iNumCUs * (uint32_t) coreInfo.iNumPEsPerCU;
FF_DEBUG("Got core count: %u", *result.coreCount);
}
else
{
} else {
FF_DEBUG("Failed to get core count");
}
}
if (result.memory)
{
if (result.memory) {
int vramUsage = 0;
int status = adlData.ffADL2_Adapter_DedicatedVRAMUsage_Get(adlData.apiHandle, device->iAdapterIndex, &vramUsage);
FF_DEBUG("ADL2_Adapter_DedicatedVRAMUsage_Get returned %s (%d), usage: %d MB",
ffAdlStatusToString(status), status, vramUsage);
ffAdlStatusToString(status),
status,
vramUsage);
if (status == ADL_OK && vramUsage >= 0) {
result.memory->used = (uint64_t) vramUsage * 1024 * 1024;
@@ -194,53 +187,48 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
}
}
if (result.memoryType)
{
if (result.memoryType) {
ADLMemoryInfo2 memoryInfo;
int status = adlData.ffADL2_Adapter_MemoryInfo2_Get(adlData.apiHandle, device->iAdapterIndex, &memoryInfo);
FF_DEBUG("ADL2_Adapter_MemoryInfo2_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (status == ADL_OK) {
FF_DEBUG("Memory info - Type: %s, Size: %lld MB", memoryInfo.strMemoryType, memoryInfo.iMemorySize / 1024 / 1024);
ffStrbufSetS(result.memoryType, memoryInfo.strMemoryType);
FF_DEBUG("Got memory type: %s", memoryInfo.strMemoryType);
}
else
{
} else {
FF_DEBUG("Failed to get memory type");
}
}
if (result.type)
{
if (result.type) {
int asicTypes = 0;
int valids = 0;
int status = adlData.ffADL2_Adapter_ASICFamilyType_Get(adlData.apiHandle, device->iAdapterIndex, &asicTypes, &valids);
FF_DEBUG("ADL2_Adapter_ASICFamilyType_Get returned %s (%d), asicTypes: 0x%x, valids: 0x%x",
ffAdlStatusToString(status), status, asicTypes, valids);
ffAdlStatusToString(status),
status,
asicTypes,
valids);
if (status == ADL_OK)
{
if (status == ADL_OK) {
asicTypes &= valids; // This design is strange
*result.type = asicTypes & ADL_ASIC_INTEGRATED ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
FF_DEBUG("GPU type: %s (asicTypes: 0x%x, valids: 0x%x)",
*result.type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete", asicTypes, valids);
}
else
{
*result.type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete",
asicTypes,
valids);
} else {
FF_DEBUG("Failed to get GPU type");
}
}
if (result.index)
{
if (result.index) {
*result.index = (uint32_t) device->iAdapterIndex;
FF_DEBUG("Setting adapter index: %u", *result.index);
}
if (result.name)
{
if (result.name) {
ffStrbufSetS(result.name, device->strAdapterName);
FF_DEBUG("Setting adapter name: %s; UDID: %s, Present: %d, Exist: %d", device->strAdapterName, device->strUDID, device->iPresent, device->iExist);
}
@@ -252,121 +240,94 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
int odEnabled = 0;
int status = adlData.ffADL2_Overdrive_Caps(adlData.apiHandle, device->iAdapterIndex, &odSupported, &odEnabled, &odVersion);
FF_DEBUG("ADL2_Overdrive_Caps returned %s (%d); supported %d, enabled %d; version %d",
ffAdlStatusToString(status), status, odSupported, odEnabled, odVersion);
if (status != ADL_OK)
{
ffAdlStatusToString(status),
status,
odSupported,
odEnabled,
odVersion);
if (status != ADL_OK) {
FF_DEBUG("Overdrive not supported, results may be inaccurate");
// Note even if Overdrive is not supported, we can still get the OD version
}
}
if (odVersion == 8)
{
if (odVersion == 8) {
FF_DEBUG("Using Overdrive8 API (odVersion=%d)", odVersion);
if (result.frequency)
{
ADLOD8CurrentSetting currentSetting = { .count = OD8_COUNT };
if (result.frequency) {
ADLOD8CurrentSetting currentSetting = {.count = OD8_COUNT};
int status = adlData.ffADL2_Overdrive8_Current_Setting_Get(adlData.apiHandle, device->iAdapterIndex, &currentSetting);
FF_DEBUG("ADL2_Overdrive8_Current_Setting_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (status == ADL_OK) {
FF_DEBUG("OD8 Settings count: %d", currentSetting.count);
*result.frequency = (uint32_t) currentSetting.Od8SettingTable[OD8_GFXCLK_FMAX];
FF_DEBUG("Got max engine clock (OD8_GFXCLK_FMAX): %u MHz", *result.frequency);
}
else
{
} else {
FF_DEBUG("Failed to get max frequency information");
}
}
if (result.temp || result.coreUsage)
{
if (result.temp || result.coreUsage) {
ADLPMLogDataOutput pmLogDataOutput = {};
int status = adlData.ffADL2_New_QueryPMLogData_Get(adlData.apiHandle, device->iAdapterIndex, &pmLogDataOutput);
FF_DEBUG("ADL2_New_QueryPMLogData_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (result.temp)
{
if (status == ADL_OK) {
if (result.temp) {
ADLSingleSensorData* sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_HOTSPOT];
FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_HOTSPOT, "ADL_PMLOG_TEMPERATURE_HOTSPOT", sensor->supported, sensor->value);
if (sensor->supported)
{
if (sensor->supported) {
*result.temp = sensor->value;
FF_DEBUG("Temperature: %.1f°C (HOTSPOT)", *result.temp);
}
else
{
} else {
sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_GFX];
FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_GFX, "ADL_PMLOG_TEMPERATURE_GFX", sensor->supported, sensor->value);
if (sensor->supported)
{
if (sensor->supported) {
*result.temp = sensor->value;
FF_DEBUG("Temperature: %.1f°C (GFX)", *result.temp);
}
else
{
} else {
sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_SOC];
FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_SOC, "ADL_PMLOG_TEMPERATURE_SOC", sensor->supported, sensor->value);
if (sensor->supported)
{
if (sensor->supported) {
*result.temp = sensor->value;
FF_DEBUG("Temperature: %.1f°C (SOC)", *result.temp);
}
else
{
} else {
FF_DEBUG("No supported temp sensor found, temp detection failed");
}
}
}
}
if (result.coreUsage)
{
if (result.coreUsage) {
ADLSingleSensorData* activity = &pmLogDataOutput.sensors[ADL_PMLOG_INFO_ACTIVITY_GFX];
FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_INFO_ACTIVITY_GFX, "ADL_PMLOG_INFO_ACTIVITY_GFX", activity->supported, activity->value);
if (activity->supported)
{
if (activity->supported) {
*result.coreUsage = activity->value;
FF_DEBUG("Core usage: %.1f%%", *result.coreUsage);
}
else
{
} else {
FF_DEBUG("Sensor %d not supported, GPU usage detection failed", ADL_PMLOG_INFO_ACTIVITY_GFX);
}
}
}
else
{
} else {
FF_DEBUG("Failed to get temperature / GPU activity");
}
}
}
else if (odVersion == 7)
{
} else if (odVersion == 7) {
FF_DEBUG("Using OverdriveN API (odVersion=%d)", odVersion);
if (result.frequency)
{
if (result.frequency) {
// https://github.com/MaynardMiner/odvii/blob/master/OverdriveN.cpp#L176
ADLODNCapabilitiesX2 odCapabilities = {};
int status = adlData.ffADL2_OverdriveN_CapabilitiesX2_Get(adlData.apiHandle, device->iAdapterIndex, &odCapabilities);
FF_DEBUG("ADL2_OverdriveN_CapabilitiesX2_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (odCapabilities.iMaximumNumberOfPerformanceLevels == 0)
{
if (status == ADL_OK) {
if (odCapabilities.iMaximumNumberOfPerformanceLevels == 0) {
FF_DEBUG("ADL2_OverdriveN_CapabilitiesX2_Get: no performance levels available");
}
else
{
} else {
FF_DEBUG("ODN Capabilities - MaxPerformanceLevels: %d, GPU Clock Range: [%d - %d]",
odCapabilities.iMaximumNumberOfPerformanceLevels,
odCapabilities.sEngineClockRange.iMin, odCapabilities.sEngineClockRange.iMax);
odCapabilities.iMaximumNumberOfPerformanceLevels,
odCapabilities.sEngineClockRange.iMin,
odCapabilities.sEngineClockRange.iMax);
size_t size = sizeof(ADLODNPerformanceLevelsX2) + sizeof(ADLODNPerformanceLevelX2) * ((unsigned) odCapabilities.iMaximumNumberOfPerformanceLevels - 1);
FF_AUTO_FREE ADLODNPerformanceLevelsX2* odPerfLevels = calloc(size, 1);
@@ -376,21 +337,18 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
int status = adlData.ffADL2_OverdriveN_SystemClocksX2_Get(adlData.apiHandle, device->iAdapterIndex, odPerfLevels);
FF_DEBUG("ADL2_OverdriveN_SystemClocksX2_Get returned %s (%d), levels: %d",
ffAdlStatusToString(status), status, odPerfLevels->iNumberOfPerformanceLevels);
ffAdlStatusToString(status),
status,
odPerfLevels->iNumberOfPerformanceLevels);
if (status != ADL_OK)
{
if (status != ADL_OK) {
FF_DEBUG("Failed to get frequency information");
}
else
{
} else {
// lowest to highest
for (int i = odPerfLevels->iNumberOfPerformanceLevels - 1; i >= 0 ; i--)
{
for (int i = odPerfLevels->iNumberOfPerformanceLevels - 1; i >= 0; i--) {
ADLODNPerformanceLevelX2* level = &odPerfLevels->aLevels[i];
FF_DEBUG("Performance level %d: enabled: %d, engine clock = %d", i, level->iEnabled, level->iClock);
if (level->iEnabled)
{
if (level->iEnabled) {
*result.frequency = (uint32_t) level->iClock / 100; // in 10 kHz
FF_DEBUG("Got max engine clock: %u MHz", *result.frequency);
break;
@@ -398,126 +356,102 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
}
}
}
}
else
{
} else {
FF_DEBUG("Failed to get frequency information");
}
}
if (result.coreUsage)
{
if (result.coreUsage) {
ADLODNPerformanceStatus performanceStatus = {};
int status = adlData.ffADL2_OverdriveN_PerformanceStatus_Get(adlData.apiHandle, device->iAdapterIndex, &performanceStatus);
FF_DEBUG("ADL2_OverdriveN_PerformanceStatus_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (status == ADL_OK) {
FF_DEBUG("Performance Status - Activity: %d%%, CoreClock: %dMHz, MemoryClock: %dMHz",
performanceStatus.iGPUActivityPercent,
performanceStatus.iCoreClock,
performanceStatus.iMemoryClock);
performanceStatus.iGPUActivityPercent,
performanceStatus.iCoreClock,
performanceStatus.iMemoryClock);
*result.coreUsage = performanceStatus.iGPUActivityPercent;
FF_DEBUG("Got GPU activity: %d%%", performanceStatus.iGPUActivityPercent);
}
else
{
} else {
FF_DEBUG("Failed to get GPU activity");
}
}
if (result.temp)
{
if (result.temp) {
int milliDegrees = 0;
int status = adlData.ffADL2_OverdriveN_Temperature_Get(adlData.apiHandle, device->iAdapterIndex, 1, &milliDegrees);
FF_DEBUG("ADL2_OverdriveN_Temperature_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (status == ADL_OK) {
*result.temp = milliDegrees / 1000.0;
FF_DEBUG("Temperature: %.1f°C (raw: %d milliC)", *result.temp, milliDegrees);
}
else
{
} else {
FF_DEBUG("Failed to get temperature");
}
}
}
else if (odVersion == 6)
{
} else if (odVersion == 6) {
FF_DEBUG("Using Overdrive6 API (odVersion=%d)", odVersion);
if (result.frequency)
{
if (result.frequency) {
FF_AUTO_FREE ADLOD6StateInfo* stateInfo = calloc(sizeof(ADLOD6StateInfo) + sizeof(ADLOD6PerformanceLevel), 1);
stateInfo->iNumberOfPerformanceLevels = 2;
int status = adlData.ffADL2_Overdrive6_StateInfo_Get(adlData.apiHandle, device->iAdapterIndex, ADL_OD6_GETSTATEINFO_CUSTOM_PERFORMANCE, stateInfo);
FF_DEBUG("ADL2_Overdrive6_StateInfo_Get returned %s (%d), performance levels: %d",
ffAdlStatusToString(status), status, stateInfo->iNumberOfPerformanceLevels);
ffAdlStatusToString(status),
status,
stateInfo->iNumberOfPerformanceLevels);
if (status == ADL_OK)
{
if (status == ADL_OK) {
// OD6 uses clock ranges instead of discrete performance levels.
// iNumberOfPerformanceLevels is always 2.
// The 1st level indicates the minimum clocks in the range.
// The 2nd level indicates the maximum clocks in the range.
if (stateInfo->iNumberOfPerformanceLevels != 2)
{
if (stateInfo->iNumberOfPerformanceLevels != 2) {
FF_DEBUG("ADL2_Overdrive6_StateInfo_Get: unexpected number of performance levels: %d", stateInfo->iNumberOfPerformanceLevels);
}
else
{
} else {
FF_DEBUG("OD6 Settings - MinPerformanceLevels: %d, MaxPerformanceLevels: %d",
stateInfo->aLevels[0].iEngineClock, stateInfo->aLevels[1].iEngineClock);
stateInfo->aLevels[0].iEngineClock,
stateInfo->aLevels[1].iEngineClock);
*result.frequency = (uint32_t) stateInfo->aLevels[1].iEngineClock / 100; // in 10 kHz
FF_DEBUG("Got max engine clock: %u MHz", *result.frequency);
}
}
else
{
} else {
FF_DEBUG("Failed to get frequency information");
}
}
if (result.coreUsage)
{
if (result.coreUsage) {
ADLOD6CurrentStatus status = {};
int apiStatus = adlData.ffADL2_Overdrive6_CurrentStatus_Get(adlData.apiHandle, device->iAdapterIndex, &status);
FF_DEBUG("ADL2_Overdrive6_CurrentStatus_Get returned %s (%d)", ffAdlStatusToString(apiStatus), apiStatus);
if (apiStatus == ADL_OK)
{
if (apiStatus == ADL_OK) {
*result.coreUsage = status.iActivityPercent;
FF_DEBUG("Got GPU activity: %d%%", status.iActivityPercent);
}
else
{
} else {
FF_DEBUG("Failed to get GPU activity");
}
}
if (result.temp)
{
if (result.temp) {
int milliDegrees = 0;
int status = adlData.ffADL2_Overdrive6_Temperature_Get(adlData.apiHandle, device->iAdapterIndex, &milliDegrees);
FF_DEBUG("ADL2_Overdrive6_Temperature_Get returned %s (%d), temperature: %d milliC",
ffAdlStatusToString(status), status, milliDegrees);
ffAdlStatusToString(status),
status,
milliDegrees);
if (status == ADL_OK)
{
if (status == ADL_OK) {
*result.temp = milliDegrees / 1000.0;
FF_DEBUG("Temperature: %.1f°C", *result.temp);
}
else
{
} else {
FF_DEBUG("Failed to get temperature");
}
}
}
else
{
} else {
FF_DEBUG("Unknown Overdrive version: %d", odVersion);
return "Unknown Overdrive version";
}
+20 -18
View File
@@ -4,50 +4,52 @@
#include <fcntl.h>
static double parseTZDir(int dfd, FFstrbuf* buffer)
{
if (!ffReadFileBufferRelative(dfd, "type", buffer) || !ffStrbufStartsWithS(buffer, "gpu"))
static double parseTZDir(int dfd, FFstrbuf* buffer) {
if (!ffReadFileBufferRelative(dfd, "type", buffer) || !ffStrbufStartsWithS(buffer, "gpu")) {
return FF_GPU_TEMP_UNSET;
}
if (!ffReadFileBufferRelative(dfd, "temp", buffer))
if (!ffReadFileBufferRelative(dfd, "temp", buffer)) {
return FF_GPU_TEMP_UNSET;
}
double value = ffStrbufToDouble(buffer, FF_GPU_TEMP_UNSET);// millidegree Celsius
if (value == FF_GPU_TEMP_UNSET)
double value = ffStrbufToDouble(buffer, FF_GPU_TEMP_UNSET); // millidegree Celsius
if (value == FF_GPU_TEMP_UNSET) {
return FF_GPU_TEMP_UNSET;
}
return value / 1000.;
}
double ffGPUDetectTempFromTZ(void)
{
double ffGPUDetectTempFromTZ(void) {
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/thermal/");
if(dirp)
{
if (dirp) {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
int dfd = dirfd(dirp);
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
if(!ffStrStartsWith(entry->d_name, "thermal_zone"))
}
if (!ffStrStartsWith(entry->d_name, "thermal_zone")) {
continue;
}
FF_AUTO_CLOSE_FD int subfd = openat(dfd, entry->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if(subfd < 0)
if (subfd < 0) {
continue;
}
double result = parseTZDir(subfd, &buffer);
if (result != FF_GPU_TEMP_UNSET)
if (result != FF_GPU_TEMP_UNSET) {
return result;
}
}
}
return FF_GPU_TEMP_UNSET;
}
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
FF_UNUSED(options, gpus);
return "No permission. Fallbacks to Vulkan, OpenCL or OpenGL instead";
}
+81 -72
View File
@@ -7,95 +7,107 @@
const char* ffGpuDetectMetal(FFlist* gpus);
const char* ffGpuDetectDriverVersion(FFlist* gpus);
static double detectGpuTemp(const FFstrbuf* gpuName)
{
static double detectGpuTemp(const FFstrbuf* gpuName) {
double result = 0;
const char* error = NULL;
if (ffStrbufStartsWithS(gpuName, "Apple M"))
{
switch (strtol(gpuName->chars + strlen("Apple M"), NULL, 10))
{
case 0: error = "Invalid Apple Silicon GPU"; break;
case 1: error = ffDetectSmcTemps(FF_TEMP_GPU_M1X, &result); break;
case 2: error = ffDetectSmcTemps(FF_TEMP_GPU_M2X, &result); break;
case 3: error = ffDetectSmcTemps(FF_TEMP_GPU_M3X, &result); break;
case 4: error = ffDetectSmcTemps(FF_TEMP_GPU_M4X, &result); break;
default: error = "Unsupported Apple Silicon GPU"; break;
if (ffStrbufStartsWithS(gpuName, "Apple M")) {
switch (strtol(gpuName->chars + strlen("Apple M"), NULL, 10)) {
case 0:
error = "Invalid Apple Silicon GPU";
break;
case 1:
error = ffDetectSmcTemps(FF_TEMP_GPU_M1X, &result);
break;
case 2:
error = ffDetectSmcTemps(FF_TEMP_GPU_M2X, &result);
break;
case 3:
error = ffDetectSmcTemps(FF_TEMP_GPU_M3X, &result);
break;
case 4:
error = ffDetectSmcTemps(FF_TEMP_GPU_M4X, &result);
break;
default:
error = "Unsupported Apple Silicon GPU";
break;
}
}
else if (ffStrbufStartsWithS(gpuName, "Intel"))
} else if (ffStrbufStartsWithS(gpuName, "Intel")) {
error = ffDetectSmcTemps(FF_TEMP_GPU_INTEL, &result);
else if (ffStrbufStartsWithS(gpuName, "Radeon") || ffStrbufStartsWithS(gpuName, "AMD"))
} else if (ffStrbufStartsWithS(gpuName, "Radeon") || ffStrbufStartsWithS(gpuName, "AMD")) {
error = ffDetectSmcTemps(FF_TEMP_GPU_AMD, &result);
else
} else {
error = ffDetectSmcTemps(FF_TEMP_GPU_UNKNOWN, &result);
}
if (error)
if (error) {
return FF_GPU_TEMP_UNSET;
}
return result;
}
#ifdef __aarch64__
#include "common/apple/cf_helpers.h"
# include "common/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
# include <IOKit/IOKitLib.h>
static const char* detectFrequency(FFGPUResult* gpu)
{
static const char* detectFrequency(FFGPUResult* gpu) {
// https://github.com/giampaolo/psutil/pull/2222/files
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
if (!entryDevice)
if (!entryDevice) {
return "IOServiceGetMatchingServices() failed";
}
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) {
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
}
FF_CFTYPE_AUTO_RELEASE CFDataRef freqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states9-sram"), kCFAllocatorDefault, kNilOptions);
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID())
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID()) {
return "\"voltage-states9-sram\" in \"pmgr\" is not found";
}
// voltage-states9-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
CFIndex propLength = CFDataGetLength(freqProperty);
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0)
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) {
return "Invalid \"voltage-states9-sram\" length";
}
uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(freqProperty);
uint32_t pMax = *pStart;
for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */)
for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */) {
pMax = pMax > pStart[i] ? pMax : pStart[i];
}
if (pMax > 0)
{
if (pMax > 0) {
// While this is not necessary for now (seems), we add this logic just in case. See cpu_apple.c
if (pMax > 100000000) // Assume that pMax is in Hz
if (pMax > 100000000) { // Assume that pMax is in Hz
gpu->frequency = pMax / 1000 / 1000;
else // Assume that pMax is in kHz
} else { // Assume that pMax is in kHz
gpu->frequency = pMax / 1000;
}
}
return NULL;
}
#endif
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
{
CFMutableDictionaryRef matches = IOServiceMatching(kIOAcceleratorClassName);
CFDictionaryAddValue(matches, CFSTR("IOMatchCategory"), CFSTR(kIOAcceleratorClassName));
if (IOServiceGetMatchingServices(MACH_PORT_NULL, matches, &iterator) != kIOReturnSuccess)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, matches, &iterator) != kIOReturnSuccess) {
return "IOServiceGetMatchingServices() failed";
}
}
io_registry_entry_t registryEntry;
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL) {
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
if (IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) {
IOObjectRelease(registryEntry);
continue;
}
@@ -112,46 +124,44 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffStrbufInit(&gpu->driver); // Ok for both Apple and Intel
ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver);
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount) != NULL) // For Apple
if (ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount) != NULL) { // For Apple
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
}
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
CFDictionaryRef perfStatistics = NULL;
uint64_t vramUsed = 0, vramTotal = 0;
if (ffCfDictGetDict(properties, CFSTR("PerformanceStatistics"), &perfStatistics) == NULL)
{
if (ffCfDictGetDict(properties, CFSTR("PerformanceStatistics"), &perfStatistics) == NULL) {
int64_t utilization;
if (ffCfDictGetInt64(perfStatistics, CFSTR("Device Utilization %"), &utilization) == NULL)
if (ffCfDictGetInt64(perfStatistics, CFSTR("Device Utilization %"), &utilization) == NULL) {
gpu->coreUsage = (double) utilization;
else if (ffCfDictGetInt64(perfStatistics, CFSTR("GPU Core Utilization"), &utilization) == NULL)
} else if (ffCfDictGetInt64(perfStatistics, CFSTR("GPU Core Utilization"), &utilization) == NULL) {
gpu->coreUsage = (double) utilization / 10000000.; // Nvidia?
if (ffCfDictGetInt64(perfStatistics, CFSTR("Alloc system memory"), (int64_t*) &vramTotal) == NULL)
{
if (ffCfDictGetInt64(perfStatistics, CFSTR("In use system memory"), (int64_t*) &vramUsed) != NULL)
vramTotal = 0;
}
else if (ffCfDictGetInt64(perfStatistics, CFSTR("vramFreeBytes"), (int64_t*) &vramTotal) == NULL)
{
if (ffCfDictGetInt64(perfStatistics, CFSTR("vramUsedBytes"), (int64_t*) &vramUsed) == NULL)
vramTotal += vramUsed;
else
if (ffCfDictGetInt64(perfStatistics, CFSTR("Alloc system memory"), (int64_t*) &vramTotal) == NULL) {
if (ffCfDictGetInt64(perfStatistics, CFSTR("In use system memory"), (int64_t*) &vramUsed) != NULL) {
vramTotal = 0;
}
} else if (ffCfDictGetInt64(perfStatistics, CFSTR("vramFreeBytes"), (int64_t*) &vramTotal) == NULL) {
if (ffCfDictGetInt64(perfStatistics, CFSTR("vramUsedBytes"), (int64_t*) &vramUsed) == NULL) {
vramTotal += vramUsed;
} else {
vramTotal = 0;
}
}
}
ffStrbufInit(&gpu->name);
//IOAccelerator returns model / vendor-id properties for Apple Silicon, but not for Intel Iris GPUs.
//Still needs testing for AMD's
if(ffCfDictGetString(properties, CFSTR("model"), &gpu->name) != NULL)
{
// IOAccelerator returns model / vendor-id properties for Apple Silicon, but not for Intel Iris GPUs.
// Still needs testing for AMD's
if (ffCfDictGetString(properties, CFSTR("model"), &gpu->name) != NULL) {
CFRelease(properties);
properties = NULL;
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t parentEntry = 0;
if(IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, &parentEntry) != kIOReturnSuccess ||
IORegistryEntryCreateCFProperties(parentEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
if (IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, &parentEntry) != kIOReturnSuccess ||
IORegistryEntryCreateCFProperties(parentEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) {
IOObjectRelease(registryEntry);
continue;
}
@@ -160,27 +170,25 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffStrbufInit(&gpu->vendor);
int vendorId;
if(ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId) == NULL)
{
if (ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId) == NULL) {
const char* vendorStr = ffGPUGetVendorString((unsigned) vendorId);
ffStrbufAppendS(&gpu->vendor, vendorStr);
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE || vendorStr == FF_GPU_VENDOR_NAME_INTEL)
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE || vendorStr == FF_GPU_VENDOR_NAME_INTEL) {
gpu->type = FF_GPU_TYPE_INTEGRATED;
else if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA || vendorStr == FF_GPU_VENDOR_NAME_AMD)
} else if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA || vendorStr == FF_GPU_VENDOR_NAME_AMD) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
#ifdef __aarch64__
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE)
#ifdef __aarch64__
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE) {
detectFrequency(gpu);
#endif
}
#endif
if (gpu->type == FF_GPU_TYPE_INTEGRATED)
{
if (gpu->type == FF_GPU_TYPE_INTEGRATED) {
gpu->shared.total = vramTotal;
gpu->shared.used = vramUsed;
}
else if (gpu->type == FF_GPU_TYPE_DISCRETE)
{
} else if (gpu->type == FF_GPU_TYPE_DISCRETE) {
gpu->dedicated.total = vramTotal;
gpu->dedicated.used = vramUsed;
}
@@ -193,7 +201,8 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
}
ffGpuDetectMetal(gpus);
if (instance.config.general.detectVersion)
if (instance.config.general.detectVersion) {
ffGpuDetectDriverVersion(gpus);
}
return NULL;
}
+87 -89
View File
@@ -6,29 +6,24 @@
#include <sys/pciio.h>
#include <fcntl.h>
#if __has_include(<dev/pci/pcireg.h>)
#include <dev/pci/pcireg.h> // FreeBSD
# include <dev/pci/pcireg.h> // FreeBSD
#else
#include <bus/pci/pcireg.h> // DragonFly
# include <bus/pci/pcireg.h> // DragonFly
#endif
static void fillGPUTypeGeneric(FFGPUResult* gpu)
{
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
static void fillGPUTypeGeneric(FFGPUResult* gpu) {
if (gpu->type == FF_GPU_TYPE_UNKNOWN) {
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
}
} 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;
}
@@ -36,32 +31,32 @@ static void fillGPUTypeGeneric(FFGPUResult* gpu)
}
#if FF_HAVE_DRM
#include "common/library.h"
#include "common/stringUtils.h"
# include "common/library.h"
# include "common/stringUtils.h"
#include <xf86drm.h>
# include <xf86drm.h>
static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
{
static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus) {
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
drmDevicePtr devices[64];
int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
if (nDevices < 0)
if (nDevices < 0) {
return "drmGetDevices() failed";
}
for (int iDev = 0; iDev < nDevices; ++iDev)
{
for (int iDev = 0; iDev < nDevices; ++iDev) {
drmDevice* dev = devices[iDev];
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY)))
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY))) {
continue;
}
const char* path = dev->nodes[DRM_NODE_PRIMARY];
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
@@ -76,28 +71,29 @@ static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
gpu->deviceId = 0;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
switch (dev->bustype)
{
case DRM_BUS_PCI:
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
gpu->deviceId = ffGPUPciAddr2Id(dev->businfo.pci->domain, dev->businfo.pci->bus, dev->businfo.pci->dev, dev->businfo.pci->func);
break;
case DRM_BUS_HOST1X:
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
gpu->type = FF_GPU_TYPE_INTEGRATED;
break;
case DRM_BUS_PLATFORM:
ffStrbufSetS(&gpu->name, dev->deviceinfo.platform->compatible[0]);
gpu->type = FF_GPU_TYPE_INTEGRATED;
break;
case DRM_BUS_USB:
ffStrbufSetF(&gpu->name, "USB Device (%u-%u)", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
gpu->type = FF_GPU_TYPE_DISCRETE;
break;
switch (dev->bustype) {
case DRM_BUS_PCI:
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
gpu->deviceId = ffGPUPciAddr2Id(dev->businfo.pci->domain, dev->businfo.pci->bus, dev->businfo.pci->dev, dev->businfo.pci->func);
break;
case DRM_BUS_HOST1X:
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
gpu->type = FF_GPU_TYPE_INTEGRATED;
break;
case DRM_BUS_PLATFORM:
ffStrbufSetS(&gpu->name, dev->deviceinfo.platform->compatible[0]);
gpu->type = FF_GPU_TYPE_INTEGRATED;
break;
case DRM_BUS_USB:
ffStrbufSetF(&gpu->name, "USB Device (%u-%u)", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
gpu->type = FF_GPU_TYPE_DISCRETE;
break;
}
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) continue;
if (fd < 0) {
continue;
}
char driverName[64];
driverName[0] = '\0';
@@ -105,40 +101,39 @@ static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
.name = driverName,
.name_len = ARRAY_SIZE(driverName),
};
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0)
{
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0) {
driverName[ver.name_len] = '\0';
ffStrbufSetF(&gpu->driver, "%s %d.%d.%d", ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel);
}
if (ffStrStartsWith(driverName, "i915"))
if (ffStrStartsWith(driverName, "i915")) {
ffDrmDetectI915(gpu, fd);
else if (ffStrStartsWith(driverName, "amdgpu"))
} else if (ffStrStartsWith(driverName, "amdgpu")) {
ffDrmDetectAmdgpu(options, gpu, dev->nodes[DRM_NODE_RENDER]);
else if (ffStrStartsWith(driverName, "radeon"))
} else if (ffStrStartsWith(driverName, "radeon")) {
ffDrmDetectRadeon(options, gpu, dev->nodes[DRM_NODE_RENDER]);
else if (ffStrStartsWith(driverName, "xe"))
} else if (ffStrStartsWith(driverName, "xe")) {
ffDrmDetectXe(gpu, fd);
else if (ffStrStartsWith(driverName, "asahi"))
} else if (ffStrStartsWith(driverName, "asahi")) {
ffDrmDetectAsahi(gpu, fd);
else if (ffStrStartsWith(driverName, "nouveau"))
} else if (ffStrStartsWith(driverName, "nouveau")) {
ffDrmDetectNouveau(gpu, fd);
else if (dev->bustype == DRM_BUS_PCI)
{
} else if (dev->bustype == DRM_BUS_PCI) {
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
.domain = (uint32_t) dev->businfo.pci->domain,
.bus = dev->businfo.pci->bus,
.device = dev->businfo.pci->dev,
.func = dev->businfo.pci->func,
});
.domain = (uint32_t) dev->businfo.pci->domain,
.bus = dev->businfo.pci->bus,
.device = dev->businfo.pci->dev,
.func = dev->businfo.pci->func,
});
}
if (gpu->name.length == 0)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
if (gpu->name.length == 0) {
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(dev->deviceinfo.pci->device_id, dev->deviceinfo.pci->revision_id, gpu);
if (gpu->name.length == 0)
}
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(0, dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id, gpu);
}
}
fillGPUTypeGeneric(gpu);
@@ -150,11 +145,11 @@ static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
}
#endif
static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
{
static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus) {
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY | O_CLOEXEC);
if (fd < 0)
if (fd < 0) {
return "open(\"/dev/pci\", O_RDONLY | O_CLOEXEC, 0) failed";
}
struct pci_conf confs[128];
struct pci_match_conf match = {
@@ -169,20 +164,22 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
.matches = confs,
};
if (ioctl(fd, PCIOCGETCONF, &pcio) < 0)
if (ioctl(fd, PCIOCGETCONF, &pcio) < 0) {
return "ioctl(fd, PCIOCGETCONF, &pc) failed";
}
if (pcio.status == PCI_GETCONF_ERROR)
if (pcio.status == PCI_GETCONF_ERROR) {
return "ioctl(fd, PCIOCGETCONF, &pc) returned error";
}
for (uint32_t i = 0; i < pcio.num_matches; ++i)
{
for (uint32_t i = 0; i < pcio.num_matches; ++i) {
struct pci_conf* pc = &confs[i];
if (pc->pc_sel.pc_func > 0 && pc->pc_subclass == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
if (pc->pc_sel.pc_func > 0 && pc->pc_subclass == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) {
continue; // Likely an auxiliary display controller (#2034)
}
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pc->pc_vendor));
ffStrbufInit(&gpu->name);
ffStrbufInitS(&gpu->driver, pc->pd_name);
@@ -198,18 +195,19 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
.domain = (uint32_t) pc->pc_sel.pc_domain,
.bus = pc->pc_sel.pc_bus,
.device = pc->pc_sel.pc_dev,
.func = pc->pc_sel.pc_func,
});
.domain = (uint32_t) pc->pc_sel.pc_domain,
.bus = pc->pc_sel.pc_bus,
.device = pc->pc_sel.pc_dev,
.func = pc->pc_sel.pc_func,
});
if (gpu->name.length == 0)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
if (gpu->name.length == 0) {
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(pc->pc_device, pc->pc_revid, gpu);
if (gpu->name.length == 0)
}
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
}
}
fillGPUTypeGeneric(gpu);
@@ -218,15 +216,15 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
return NULL;
}
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
#if FF_HAVE_DRM
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
{
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
#if FF_HAVE_DRM
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO) {
detectByDrm(options, gpus);
if (gpus->length > 0) return NULL;
if (gpus->length > 0) {
return NULL;
}
}
#endif
#endif
return detectByPci(options, gpus);
}
+28 -40
View File
@@ -2,16 +2,14 @@
#include "gpu.h"
typedef enum __attribute__((__packed__)) FFGpuDriverConditionType
{
typedef enum __attribute__((__packed__)) FFGpuDriverConditionType {
FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID = 1 << 0,
FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID = 1 << 1,
FF_GPU_DRIVER_CONDITION_TYPE_LUID = 1 << 2,
FF_GPU_DRIVER_CONDITION_TYPE_FORCE_UNSIGNED = UINT8_MAX,
} FFGpuDriverConditionType;
typedef struct FFGpuDriverPciDeviceId
{
typedef struct FFGpuDriverPciDeviceId {
uint32_t deviceId;
uint32_t vendorId;
uint32_t subSystemId;
@@ -19,8 +17,7 @@ typedef struct FFGpuDriverPciDeviceId
} FFGpuDriverPciDeviceId;
// Use pciBusId if not NULL; use pciDeviceId otherwise
typedef struct FFGpuDriverCondition
{
typedef struct FFGpuDriverCondition {
FFGpuDriverConditionType type;
FFGpuDriverPciBusId pciBusId;
FFGpuDriverPciDeviceId pciDeviceId;
@@ -28,8 +25,7 @@ typedef struct FFGpuDriverCondition
} FFGpuDriverCondition;
// detect x if not NULL
typedef struct FFGpuDriverResult
{
typedef struct FFGpuDriverResult {
uint32_t* index;
double* temp;
FFGPUMemory* memory;
@@ -47,48 +43,40 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
const char* ffDetectMthreadsGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
FF_MAYBE_UNUSED static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName)
{
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA)
{
FF_MAYBE_UNUSED static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName) {
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA) {
*pDetectFn = ffDetectNvidiaGpuInfo;
#ifdef _WIN32
#ifdef _WIN32
*pDllName = "nvml.dll";
#else
#else
*pDllName = "libnvidia-ml.so";
#endif
}
else if (vendor == FF_GPU_VENDOR_NAME_MTHREADS)
{
#endif
} else if (vendor == FF_GPU_VENDOR_NAME_MTHREADS) {
*pDetectFn = ffDetectMthreadsGpuInfo;
#ifdef _WIN32
#ifdef _WIN32
*pDllName = "mtml.dll";
#else
#else
*pDllName = "libmtml.so";
#endif
#endif
}
#ifdef _WIN32
else if (vendor == FF_GPU_VENDOR_NAME_INTEL)
{
#ifdef _WIN32
else if (vendor == FF_GPU_VENDOR_NAME_INTEL) {
*pDetectFn = ffDetectIntelGpuInfo;
#ifdef _WIN64
*pDllName = "ControlLib.dll";
#else
*pDllName = "ControlLib32.dll";
#endif
}
else if (vendor == FF_GPU_VENDOR_NAME_AMD)
{
# ifdef _WIN64
*pDllName = "ControlLib.dll";
# else
*pDllName = "ControlLib32.dll";
# endif
} else if (vendor == FF_GPU_VENDOR_NAME_AMD) {
*pDetectFn = ffDetectAmdGpuInfo;
#ifdef _WIN64
*pDllName = "atiadlxx.dll";
#else
*pDllName = "atiadlxy.dll";
#endif
# ifdef _WIN64
*pDllName = "atiadlxx.dll";
# else
*pDllName = "atiadlxy.dll";
# endif
}
#endif
else
{
#endif
else {
*pDetectFn = NULL;
*pDllName = NULL;
return false;
+144 -160
View File
@@ -1,84 +1,87 @@
#include "gpu.h"
#if FF_HAVE_DRM
#include <drm.h>
#include <fcntl.h>
#include <sys/ioctl.h>
# include <drm.h>
# include <fcntl.h>
# include <sys/ioctl.h>
#include "common/io.h"
#include "common/library.h"
#include "common/mallocHelper.h"
#include "common/stringUtils.h"
# include "common/io.h"
# include "common/library.h"
# include "common/mallocHelper.h"
# include "common/stringUtils.h"
#include "intel_drm.h"
#include "asahi_drm.h"
#include <radeon_drm.h>
#include <nouveau_drm.h>
# include "intel_drm.h"
# include "asahi_drm.h"
# include <radeon_drm.h>
# include <nouveau_drm.h>
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath)
{
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath) {
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "Failed to open DRM render device";
if (fd < 0) {
return "Failed to open DRM render device";
}
uint32_t value;
// https://github.com/torvalds/linux/blob/fb4d33ab452ea254e2c319bac5703d1b56d895bf/drivers/gpu/drm/radeon/radeon_kms.c#L231
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_ACTIVE_CU_COUNT,
.value = (uintptr_t) &value,
}) >= 0)
.request = RADEON_INFO_ACTIVE_CU_COUNT,
.value = (uintptr_t) &value,
}) >= 0) {
gpu->coreCount = (int32_t) value;
}
if (options->temp)
{
if (options->temp) {
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_CURRENT_GPU_TEMP, // millidegrees C
.value = (uintptr_t) &value,
}) >= 0 && value != 0) // 0 means unavailable
.request = RADEON_INFO_CURRENT_GPU_TEMP, // millidegrees C
.value = (uintptr_t) &value,
}) >= 0 &&
value != 0) { // 0 means unavailable
gpu->temperature = (double) value / 1000.0;
}
}
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_MAX_SCLK, // MHz
.value = (uintptr_t) &value,
}) >= 0)
.request = RADEON_INFO_MAX_SCLK, // MHz
.value = (uintptr_t) &value,
}) >= 0) {
gpu->frequency = (uint32_t) (value / 1000u);
}
if (options->driverSpecific)
{
if (options->driverSpecific) {
struct drm_radeon_gem_info gemInfo;
if (ioctl(fd, DRM_IOCTL_RADEON_GEM_INFO, &gemInfo) >= 0)
{
if (ioctl(fd, DRM_IOCTL_RADEON_GEM_INFO, &gemInfo) >= 0) {
// vram_usage can be bigger than vram_usage, so we use vram_size here
gpu->dedicated.total = gemInfo.vram_size;
gpu->shared.total = gemInfo.gart_size;
uint64_t memSize;
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_VRAM_USAGE, // uint64_t
.value = (uintptr_t) &memSize,
}) >= 0)
.request = RADEON_INFO_VRAM_USAGE, // uint64_t
.value = (uintptr_t) &memSize,
}) >= 0) {
gpu->dedicated.used = memSize;
}
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
.request = RADEON_INFO_GTT_USAGE, // uint64_t
.value = (uintptr_t) &memSize,
}) >= 0)
.request = RADEON_INFO_GTT_USAGE, // uint64_t
.value = (uintptr_t) &memSize,
}) >= 0) {
gpu->shared.used = memSize;
}
}
}
return NULL;
}
#ifdef FF_HAVE_DRM_AMDGPU
#include <amdgpu.h>
#include <amdgpu_drm.h>
# ifdef FF_HAVE_DRM_AMDGPU
# include <amdgpu.h>
# include <amdgpu_drm.h>
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath)
{
#if FF_HAVE_DRM_AMDGPU
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath) {
# if FF_HAVE_DRM_AMDGPU
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
@@ -88,33 +91,37 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "Failed to open DRM render device";
if (fd < 0) {
return "Failed to open DRM render device";
}
amdgpu_device_handle handle;
uint32_t majorVersion, minorVersion;
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0)
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0) {
return "Failed to initialize AMDGPU device";
}
uint32_t value;
if (options->temp)
{
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0)
if (options->temp) {
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0) {
gpu->temperature = value / 1000.;
}
}
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
struct amdgpu_gpu_info gpuInfo;
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0)
{
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0) {
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
#define FF_VRAM_CASE(name, value) case value /* AMDGPU_VRAM_TYPE_ ## name */: ffStrbufSetStatic(&gpu->memoryType, #name); break
switch (gpuInfo.vram_type)
{
# define FF_VRAM_CASE(name, value) \
case value /* AMDGPU_VRAM_TYPE_ ## name */: \
ffStrbufSetStatic(&gpu->memoryType, #name); \
break
switch (gpuInfo.vram_type) {
FF_VRAM_CASE(UNKNOWN, 0);
FF_VRAM_CASE(GDDR1, 1);
FF_VRAM_CASE(DDR2, 2);
@@ -128,44 +135,43 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
FF_VRAM_CASE(DDR5, 10);
FF_VRAM_CASE(LPDDR4, 11);
FF_VRAM_CASE(LPDDR5, 12);
default:
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
break;
default:
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
break;
}
struct amdgpu_heap_info heapInfo;
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0)
{
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0) {
gpu->dedicated.total = heapInfo.heap_size;
gpu->dedicated.used = heapInfo.heap_usage;
}
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_GTT, 0, &heapInfo) >= 0)
{
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_GTT, 0, &heapInfo) >= 0) {
gpu->shared.total = heapInfo.heap_size;
gpu->shared.used = heapInfo.heap_usage;
}
}
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0)
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0) {
gpu->coreUsage = value;
}
ffamdgpu_device_deinitialize(handle);
return NULL;
#else
# else
FF_UNUSED(options, gpu, renderPath);
return "Fastfetch is compiled without libdrm support";
#endif
# endif
}
#endif
# endif
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd)
{
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd) {
{
int value;
drm_i915_getparam_t getparam = { .param = I915_PARAM_EU_TOTAL, .value = &value };
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0)
drm_i915_getparam_t getparam = {.param = I915_PARAM_EU_TOTAL, .value = &value};
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0) {
gpu->coreCount = value;
}
}
{
struct drm_i915_query_item queryItem = {
@@ -175,27 +181,23 @@ const char* ffDrmDetectI915(FFGPUResult* gpu, int fd)
.items_ptr = (uintptr_t) &queryItem,
.num_items = 1,
};
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0 )
{
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0) {
FF_AUTO_FREE uint8_t* buffer = calloc(1, (size_t) queryItem.length);
queryItem.data_ptr = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0)
{
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0) {
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
struct drm_i915_query_memory_regions* regionInfo = (void*) buffer;
for (uint32_t i = 0; i < regionInfo->num_regions; i++)
{
for (uint32_t i = 0; i < regionInfo->num_regions; i++) {
struct drm_i915_memory_region_info* region = regionInfo->regions + i;
switch (region->region.memory_class)
{
case I915_MEMORY_CLASS_SYSTEM:
gpu->shared.total += region->probed_size;
gpu->shared.used += region->probed_size - region->unallocated_size;
break;
case I915_MEMORY_CLASS_DEVICE:
gpu->dedicated.total += region->probed_size;
gpu->dedicated.used += region->probed_size - region->unallocated_size;
break;
switch (region->region.memory_class) {
case I915_MEMORY_CLASS_SYSTEM:
gpu->shared.total += region->probed_size;
gpu->shared.used += region->probed_size - region->unallocated_size;
break;
case I915_MEMORY_CLASS_DEVICE:
gpu->dedicated.total += region->probed_size;
gpu->dedicated.used += region->probed_size - region->unallocated_size;
break;
}
}
}
@@ -204,54 +206,44 @@ const char* ffDrmDetectI915(FFGPUResult* gpu, int fd)
return NULL;
}
static inline int popcountBytes(uint8_t* bytes, uint32_t length)
{
static inline int popcountBytes(uint8_t* bytes, uint32_t length) {
int count = 0;
while (length >= 8)
{
while (length >= 8) {
count += __builtin_popcountll(*(uint64_t*) bytes);
bytes += 8;
length -= 8;
}
if (length >= 4)
{
if (length >= 4) {
count += __builtin_popcountl(*(uint32_t*) bytes);
bytes += 4;
length -= 4;
}
if (length >= 2)
{
if (length >= 2) {
count += __builtin_popcountl(*(uint16_t*) bytes);
bytes += 2;
length -= 2;
}
if (length)
{
if (length) {
count += __builtin_popcountl(*(uint8_t*) bytes);
}
return count;
}
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd)
{
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd) {
bool flag = false;
{
struct drm_xe_device_query query = {
.query = DRM_XE_DEVICE_QUERY_GT_TOPOLOGY,
};
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0) {
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
query.data = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0) {
int dssCount = 0, euPerDssCount = 0;
for (struct drm_xe_query_topology_mask* topo = (void*) buffer;
(uint8_t*) topo < buffer + query.size;
topo = (void*) (topo->mask + topo->num_bytes)
) {
switch (topo->type)
{
topo = (void*) (topo->mask + topo->num_bytes)) {
switch (topo->type) {
case DRM_XE_TOPO_DSS_COMPUTE:
case DRM_XE_TOPO_DSS_GEOMETRY:
dssCount += popcountBytes(topo->mask, topo->num_bytes);
@@ -271,19 +263,15 @@ const char* ffDrmDetectXe(FFGPUResult* gpu, int fd)
struct drm_xe_device_query query = {
.query = DRM_XE_DEVICE_QUERY_MEM_REGIONS,
};
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0) {
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
query.data = (uintptr_t) buffer;
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
{
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0) {
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
struct drm_xe_query_mem_regions* regionInfo = (void*) buffer;
for (uint32_t i = 0; i < regionInfo->num_mem_regions; i++)
{
for (uint32_t i = 0; i < regionInfo->num_mem_regions; i++) {
struct drm_xe_mem_region* region = regionInfo->mem_regions + i;
switch (region->mem_class)
{
switch (region->mem_class) {
case DRM_XE_MEM_REGION_CLASS_SYSMEM:
gpu->shared.total += region->total_size;
gpu->shared.used += region->used;
@@ -301,41 +289,35 @@ const char* ffDrmDetectXe(FFGPUResult* gpu, int fd)
return flag ? NULL : "Failed to query Xe GPU information";
}
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd)
{
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd) {
struct drm_asahi_params_global paramsGlobal = {};
if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) {
.param_group = DRM_ASAHI_GET_PARAMS,
.pointer = (uintptr_t) &paramsGlobal,
.size = sizeof(paramsGlobal),
}) >= 0)
{
.param_group = DRM_ASAHI_GET_PARAMS,
.pointer = (uintptr_t) &paramsGlobal,
.size = sizeof(paramsGlobal),
}) >= 0) {
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = ffGPUGeneral2Id(paramsGlobal.chip_id);
if (!gpu->name.length)
{
if (!gpu->name.length) {
const char* variant = " Unknown";
switch (paramsGlobal.gpu_variant) {
case 'G':
variant = "";
break;
case 'S':
variant = " Pro";
break;
case 'C':
variant = " Max";
break;
case 'D':
variant = " Ultra";
break;
case 'G':
variant = "";
break;
case 'S':
variant = " Pro";
break;
case 'C':
variant = " Max";
break;
case 'D':
variant = " Ultra";
break;
}
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)",
paramsGlobal.gpu_generation - 12, variant,
paramsGlobal.gpu_generation, paramsGlobal.gpu_variant,
paramsGlobal.gpu_revision + 0xA0);
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)", paramsGlobal.gpu_generation - 12, variant, paramsGlobal.gpu_generation, paramsGlobal.gpu_variant, paramsGlobal.gpu_revision + 0xA0);
}
return NULL;
@@ -344,25 +326,27 @@ const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd)
return "Failed to query Asahi GPU information";
}
#ifndef DRM_IOCTL_NOUVEAU_GETPARAM
#define DRM_IOCTL_NOUVEAU_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GETPARAM, struct drm_nouveau_getparam)
#endif
# ifndef DRM_IOCTL_NOUVEAU_GETPARAM
# define DRM_IOCTL_NOUVEAU_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GETPARAM, struct drm_nouveau_getparam)
# endif
const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd)
{
struct drm_nouveau_getparam getparam = { };
const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd) {
struct drm_nouveau_getparam getparam = {};
getparam.param = NOUVEAU_GETPARAM_FB_SIZE;
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0)
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0) {
gpu->dedicated.total = getparam.value;
}
getparam.param = NOUVEAU_GETPARAM_AGP_SIZE;
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0)
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0) {
gpu->shared.total = getparam.value;
}
getparam.param = NOUVEAU_GETPARAM_GRAPH_UNITS;
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0 && getparam.value < INT32_MAX)
if (ioctl(fd, DRM_IOCTL_NOUVEAU_GETPARAM, &getparam) == 0 && getparam.value < INT32_MAX) {
gpu->coreCount = (int32_t) getparam.value;
}
return NULL;
}
@@ -371,25 +355,25 @@ const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd)
#include "gpu_driver_specific.h"
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId)
{
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId) {
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* soName;
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific))
{
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific)) {
return detectFn(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = pciBusId,
}, (FFGpuDriverResult) {
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = &gpu->name,
}, soName);
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = pciBusId,
},
(FFGpuDriverResult) {
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = &gpu->name,
},
soName);
}
return "No driver-specific detection function found for the GPU vendor";
+59 -36
View File
@@ -6,69 +6,87 @@
#include <hurd/paths.h>
enum {
PCI_VENDOR_ID = 0x00,
PCI_DEVICE_ID = 0x02,
PCI_REVISION_ID = 0x08,
PCI_CLASS_PROG = 0x09,
PCI_SUBCLASS = 0x0a,
PCI_VENDOR_ID = 0x00,
PCI_DEVICE_ID = 0x02,
PCI_REVISION_ID = 0x08,
PCI_CLASS_PROG = 0x09,
PCI_SUBCLASS = 0x0a,
PCI_CLASS_DEVICE = 0x0b,
PCI_CONF_SIZE = 0x40,
PCI_CONF_SIZE = 0x40,
};
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) {
int dDomainFd = open(_SERVERS_BUS "/pci/0000", O_RDONLY | O_CLOEXEC);
if (dDomainFd < 0) return "open(_SERVERS_BUS \"/pci/0000\") failed";
if (dDomainFd < 0) {
return "open(_SERVERS_BUS \"/pci/0000\") failed";
}
FF_AUTO_CLOSE_DIR DIR* dirDomain = fdopendir(dDomainFd);
if (dirDomain == NULL) return "fdopendir(domain) failed";
if (dirDomain == NULL) {
return "fdopendir(domain) failed";
}
struct dirent* busEntry;
while ((busEntry = readdir(dirDomain)) != NULL)
{
if (busEntry->d_type != DT_DIR || busEntry->d_name[0] == '.')
while ((busEntry = readdir(dirDomain)) != NULL) {
if (busEntry->d_type != DT_DIR || busEntry->d_name[0] == '.') {
continue;
}
char* endptr;
uint16_t pciBus = (uint16_t) strtoul(busEntry->d_name, &endptr, 16);
if (*endptr != '\0') continue;
if (*endptr != '\0') {
continue;
}
int dBusFd = openat(dDomainFd, busEntry->d_name, O_RDONLY | O_CLOEXEC);
if (dBusFd < 0) continue;
if (dBusFd < 0) {
continue;
}
FF_AUTO_CLOSE_DIR DIR* dirBus = fdopendir(dBusFd);
if (dirBus == NULL) continue;
if (dirBus == NULL) {
continue;
}
struct dirent* devEntry;
while ((devEntry = readdir(dirBus)) != NULL)
{
if (devEntry->d_type != DT_DIR || devEntry->d_name[0] == '.')
while ((devEntry = readdir(dirBus)) != NULL) {
if (devEntry->d_type != DT_DIR || devEntry->d_name[0] == '.') {
continue;
}
uint8_t pciDev = (uint8_t) strtoul(devEntry->d_name, &endptr, 16);
if (*endptr != '\0') continue;
if (*endptr != '\0') {
continue;
}
int dDevFd = openat(dBusFd, devEntry->d_name, O_RDONLY | O_CLOEXEC);
if (dDevFd < 0) continue;
if (dDevFd < 0) {
continue;
}
FF_AUTO_CLOSE_DIR DIR* dirDev = fdopendir(dDevFd);
if (dirDev == NULL) continue;
if (dirDev == NULL) {
continue;
}
struct dirent* funcEntry;
while ((funcEntry = readdir(dirDev)) != NULL)
{
if (funcEntry->d_type != DT_DIR || funcEntry->d_name[0] == '.')
while ((funcEntry = readdir(dirDev)) != NULL) {
if (funcEntry->d_type != DT_DIR || funcEntry->d_name[0] == '.') {
continue;
}
uint8_t pciFunc = (uint8_t) strtoul(funcEntry->d_name, &endptr, 16);
if (*endptr != '\0') continue;
if (*endptr != '\0') {
continue;
}
char subpath[PATH_MAX];
snprintf(subpath, ARRAY_SIZE(subpath), "%s/%s/%s/%s/config", _SERVERS_BUS "/pci/0000", busEntry->d_name, devEntry->d_name, funcEntry->d_name);
mach_port_t devicePort = file_name_lookup(subpath, 0, 0);
if (devicePort == MACH_PORT_NULL)
if (devicePort == MACH_PORT_NULL) {
continue;
}
mach_msg_type_number_t nread = 0;
@@ -76,27 +94,30 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
data_t pData = (data_t) data;
kern_return_t kr = pci_conf_read(devicePort, 0, &pData, &nread, PCI_CONF_SIZE);
mach_port_deallocate(mach_task_self(), devicePort);
if (kr != KERN_SUCCESS || nread < PCI_CONF_SIZE) continue;
if (kr != KERN_SUCCESS || nread < PCI_CONF_SIZE) {
continue;
}
if (pData != (data_t) data)
{
if (pData != (data_t) data) {
memcpy(data, pData, PCI_CONF_SIZE);
vm_deallocate(mach_task_self(), (vm_address_t)pData, nread);
vm_deallocate(mach_task_self(), (vm_address_t) pData, nread);
}
uint8_t classBase = data[PCI_CLASS_DEVICE];
if (classBase != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
if (classBase != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) {
continue;
}
uint8_t classSub = data[PCI_SUBCLASS];
if (pciFunc > 0 && classSub == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) // Likely an auxiliary display controller (#2034)
if (pciFunc > 0 && classSub == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) { // Likely an auxiliary display controller (#2034)
continue;
}
uint8_t revision = data[PCI_REVISION_ID];
uint16_t vendorId = data[PCI_VENDOR_ID] | (data[PCI_VENDOR_ID + 1] << 8);
uint16_t deviceId = data[PCI_DEVICE_ID] | (data[PCI_DEVICE_ID + 1] << 8);
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
@@ -110,11 +131,13 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(deviceId, revision, gpu);
}
if (gpu->name.length == 0)
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(classSub, vendorId, deviceId, gpu);
}
}
}
}
+14 -10
View File
@@ -3,10 +3,11 @@
#include <private/drivers/poke.h>
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) {
FF_AUTO_CLOSE_FD int pokefd = open(POKE_DEVICE_FULLNAME, O_RDWR | O_CLOEXEC);
if (pokefd < 0) return "open(POKE_DEVICE_FULLNAME) failed";
if (pokefd < 0) {
return "open(POKE_DEVICE_FULLNAME) failed";
}
pci_info dev;
pci_info_args cmd = {
@@ -14,15 +15,16 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
.info = &dev,
};
for (cmd.index = 0; ioctl(pokefd, POKE_GET_NTH_PCI_INFO, &cmd, sizeof(cmd)) == B_OK && cmd.status == B_OK; ++cmd.index)
{
if (dev.class_base != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
for (cmd.index = 0; ioctl(pokefd, POKE_GET_NTH_PCI_INFO, &cmd, sizeof(cmd)) == B_OK && cmd.status == B_OK; ++cmd.index) {
if (dev.class_base != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) {
continue;
}
if (dev.function > 0 && dev.class_sub == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
if (dev.function > 0 && dev.class_sub == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) {
continue; // Likely an auxiliary display controller (#2034)
}
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev.vendor_id));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
@@ -36,11 +38,13 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->deviceId = ffGPUPciAddr2Id(0, dev.bus, dev.device, dev.function);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(dev.device_id, dev.revision, gpu);
}
if (gpu->name.length == 0)
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(dev.class_sub, dev.vendor_id, dev.device_id, gpu);
}
}
return NULL;
+67 -84
View File
@@ -21,21 +21,17 @@ struct FFIgclData {
ctl_api_handle_t apiHandle;
} igclData;
static void shutdownIgcl()
{
if (igclData.apiHandle)
{
static void shutdownIgcl() {
if (igclData.apiHandle) {
igclData.ffctlClose(igclData.apiHandle);
igclData.apiHandle = NULL;
}
}
const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName)
{
if (!igclData.inited)
{
const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) {
if (!igclData.inited) {
igclData.inited = true;
FF_LIBRARY_LOAD(libigcl, "dlopen igcl (ControlLib) failed", soName , 1);
FF_LIBRARY_LOAD(libigcl, "dlopen igcl (ControlLib) failed", soName, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libigcl, ctlInit)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlClose)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumerateDevices)
@@ -49,28 +45,34 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlFrequencyGetProperties)
if (ffctlInit(&(ctl_init_args_t) {
.AppVersion = CTL_IMPL_VERSION,
.flags = CTL_INIT_FLAG_USE_LEVEL_ZERO,
.Size = sizeof(ctl_init_args_t),
.Version = 0,
}, &igclData.apiHandle) != CTL_RESULT_SUCCESS)
.AppVersion = CTL_IMPL_VERSION,
.flags = CTL_INIT_FLAG_USE_LEVEL_ZERO,
.Size = sizeof(ctl_init_args_t),
.Version = 0,
},
&igclData.apiHandle) != CTL_RESULT_SUCCESS) {
return "loading igcl library failed";
}
atexit(shutdownIgcl);
libigcl = NULL; // don't close igcl
}
if (!igclData.apiHandle)
if (!igclData.apiHandle) {
return "loading igcl library failed";
}
uint32_t deviceCount = 0;
if (igclData.ffctlEnumerateDevices(igclData.apiHandle, &deviceCount, NULL))
if (igclData.ffctlEnumerateDevices(igclData.apiHandle, &deviceCount, NULL)) {
return "ctlEnumerateDevices(NULL) failed";
if (deviceCount == 0)
}
if (deviceCount == 0) {
return "No Intel graphics adapter found";
}
FF_AUTO_FREE ctl_device_adapter_handle_t* devices = malloc(deviceCount * sizeof(*devices));
if (igclData.ffctlEnumerateDevices(igclData.apiHandle, &deviceCount, devices))
if (igclData.ffctlEnumerateDevices(igclData.apiHandle, &deviceCount, devices)) {
return "ctlEnumerateDevices(devices) failed";
}
ctl_device_adapter_handle_t device = NULL;
@@ -81,73 +83,65 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
.device_id_size = sizeof(deviceId),
.Version = 2,
};
for (uint32_t iDev = 0; iDev < deviceCount; iDev++)
{
if (igclData.ffctlGetDeviceProperties(devices[iDev], &properties) != CTL_RESULT_SUCCESS)
for (uint32_t iDev = 0; iDev < deviceCount; iDev++) {
if (igclData.ffctlGetDeviceProperties(devices[iDev], &properties) != CTL_RESULT_SUCCESS) {
continue;
}
if (properties.device_type != CTL_DEVICE_TYPE_GRAPHICS)
if (properties.device_type != CTL_DEVICE_TYPE_GRAPHICS) {
continue;
}
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
{
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) {
if (cond->pciBusId.bus == properties.adapter_bdf.bus &&
cond->pciBusId.device == properties.adapter_bdf.device &&
cond->pciBusId.func == properties.adapter_bdf.function)
{
cond->pciBusId.func == properties.adapter_bdf.function) {
device = devices[iDev];
break;
}
}
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_LUID)
{
if (cond->luid == deviceId)
{
} else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_LUID) {
if (cond->luid == deviceId) {
device = devices[iDev];
break;
}
}
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID)
{
} else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID) {
if (
cond->pciDeviceId.deviceId == properties.pci_device_id &&
cond->pciDeviceId.vendorId == properties.pci_vendor_id &&
cond->pciDeviceId.subSystemId == (uint32_t) ((properties.pci_subsys_id << 16u) | properties.pci_subsys_vendor_id) &&
cond->pciDeviceId.revId == properties.rev_id)
{
cond->pciDeviceId.revId == properties.rev_id) {
device = devices[iDev];
break;
}
}
}
if (!device)
if (!device) {
return "Device not found";
}
if (result.coreCount)
if (result.coreCount) {
*result.coreCount = properties.num_slices * properties.num_sub_slices_per_slice * properties.num_eus_per_sub_slice;
}
if (result.memory)
{
if (result.memory) {
ctl_mem_handle_t memoryModules[16];
uint32_t memoryCount = ARRAY_SIZE(memoryModules);
if (igclData.ffctlEnumMemoryModules(device, &memoryCount, memoryModules) == CTL_RESULT_SUCCESS && memoryCount > 0)
{
if (igclData.ffctlEnumMemoryModules(device, &memoryCount, memoryModules) == CTL_RESULT_SUCCESS && memoryCount > 0) {
result.memory->used = 0;
result.memory->total = 0;
for (uint32_t iMem = 0; iMem < memoryCount; iMem++)
{
for (uint32_t iMem = 0; iMem < memoryCount; iMem++) {
ctl_mem_properties_t memoryProperties = {
.Size = sizeof(memoryProperties),
.Version = 0,
};
if (igclData.ffctlMemoryGetProperties(memoryModules[iMem], &memoryProperties) == CTL_RESULT_SUCCESS)
{
if (memoryProperties.location == CTL_MEM_LOC_DEVICE && result.memoryType)
{
switch (memoryProperties.type)
{
#define FF_ICTL_MEM_TYPE_CASE(type) case CTL_MEM_TYPE_##type: ffStrbufSetStatic(result.memoryType, #type); break
if (igclData.ffctlMemoryGetProperties(memoryModules[iMem], &memoryProperties) == CTL_RESULT_SUCCESS) {
if (memoryProperties.location == CTL_MEM_LOC_DEVICE && result.memoryType) {
switch (memoryProperties.type) {
#define FF_ICTL_MEM_TYPE_CASE(type) \
case CTL_MEM_TYPE_##type: \
ffStrbufSetStatic(result.memoryType, #type); \
break
FF_ICTL_MEM_TYPE_CASE(HBM);
FF_ICTL_MEM_TYPE_CASE(DDR);
FF_ICTL_MEM_TYPE_CASE(DDR3);
@@ -163,7 +157,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
FF_ICTL_MEM_TYPE_CASE(GDDR6);
FF_ICTL_MEM_TYPE_CASE(GDDR6X);
FF_ICTL_MEM_TYPE_CASE(GDDR7);
#undef FF_ICTL_MEM_TYPE_CASE
#undef FF_ICTL_MEM_TYPE_CASE
default:
ffStrbufSetF(result.memoryType, "Unknown (%u)", memoryProperties.type);
break;
@@ -174,15 +168,11 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
.Size = sizeof(ctl_mem_state_t),
.Version = 0,
};
if (igclData.ffctlMemoryGetState(memoryModules[iMem], &memoryState) == CTL_RESULT_SUCCESS)
{
if (memoryProperties.location == CTL_MEM_LOC_DEVICE)
{
if (igclData.ffctlMemoryGetState(memoryModules[iMem], &memoryState) == CTL_RESULT_SUCCESS) {
if (memoryProperties.location == CTL_MEM_LOC_DEVICE) {
result.memory->total += memoryState.size;
result.memory->used += memoryState.size - memoryState.free;
}
else if (result.sharedMemory && memoryProperties.location == CTL_MEM_LOC_SYSTEM)
{
} else if (result.sharedMemory && memoryProperties.location == CTL_MEM_LOC_SYSTEM) {
result.sharedMemory->total += memoryState.size;
result.sharedMemory->used += memoryState.size - memoryState.free;
}
@@ -192,27 +182,22 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
}
}
if (result.type)
{
if (result.type) {
*result.type = properties.graphics_adapter_properties & CTL_ADAPTER_PROPERTIES_FLAG_INTEGRATED
? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
? FF_GPU_TYPE_INTEGRATED
: FF_GPU_TYPE_DISCRETE;
}
if (result.temp)
{
if (result.temp) {
ctl_temp_handle_t sensors[16];
uint32_t sensorCount = ARRAY_SIZE(sensors);
if (igclData.ffctlEnumTemperatureSensors(device, &sensorCount, sensors) == CTL_RESULT_SUCCESS && sensorCount > 0)
{
for (uint32_t iSensor = 0; iSensor < sensorCount; iSensor++)
{
ctl_temp_properties_t props = { .Size = sizeof(props) };
if (igclData.ffctlEnumTemperatureSensors(device, &sensorCount, sensors) == CTL_RESULT_SUCCESS && sensorCount > 0) {
for (uint32_t iSensor = 0; iSensor < sensorCount; iSensor++) {
ctl_temp_properties_t props = {.Size = sizeof(props)};
// The official sample code does not set Version
// https://github.com/intel/drivers.gpu.control-library/blob/1bbacbf3814f2fd0d2b930cdf42fad83f3628db9/Samples/Telemetry_Samples/Sample_TelemetryAPP.cpp#L256
if (igclData.ffctlTemperatureGetProperties(sensors[iSensor], &props) == CTL_RESULT_SUCCESS)
{
if (props.type == CTL_TEMP_SENSORS_GPU)
{
if (igclData.ffctlTemperatureGetProperties(sensors[iSensor], &props) == CTL_RESULT_SUCCESS) {
if (props.type == CTL_TEMP_SENSORS_GPU) {
*result.temp = props.maxTemperature;
break;
}
@@ -221,28 +206,26 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
}
}
if (result.frequency)
{
if (result.frequency) {
ctl_freq_handle_t domains[16];
uint32_t domainCount = ARRAY_SIZE(domains);
if (igclData.ffctlEnumFrequencyDomains(device, &domainCount, domains) == CTL_RESULT_SUCCESS && domainCount > 0)
{
if (igclData.ffctlEnumFrequencyDomains(device, &domainCount, domains) == CTL_RESULT_SUCCESS && domainCount > 0) {
double maxValue = 0;
ctl_freq_properties_t props = { .Size = sizeof(props), .Version = 0 };
for (uint32_t iDomain = 0; iDomain < domainCount; iDomain++)
{
if (igclData.ffctlFrequencyGetProperties(domains[iDomain], &props) == CTL_RESULT_SUCCESS)
{
if (props.type == CTL_FREQ_DOMAIN_GPU && props.max > maxValue)
ctl_freq_properties_t props = {.Size = sizeof(props), .Version = 0};
for (uint32_t iDomain = 0; iDomain < domainCount; iDomain++) {
if (igclData.ffctlFrequencyGetProperties(domains[iDomain], &props) == CTL_RESULT_SUCCESS) {
if (props.type == CTL_FREQ_DOMAIN_GPU && props.max > maxValue) {
maxValue = props.max;
}
}
}
*result.frequency = (uint32_t) (maxValue + 0.5);
}
}
if (result.name)
if (result.name) {
ffStrbufSetS(result.name, properties.name);
}
return NULL;
}
+232 -240
View File
@@ -13,69 +13,63 @@
#include <stdint.h>
#ifdef FF_HAVE_DRM_AMDGPU
#include <amdgpu.h>
#include <amdgpu_drm.h>
#include <fcntl.h>
# include <amdgpu.h>
# include <amdgpu_drm.h>
# include <fcntl.h>
#endif
#ifdef FF_HAVE_DRM
#include "intel_drm.h"
#include <fcntl.h>
#include <sys/ioctl.h>
# include "intel_drm.h"
# include <fcntl.h>
# include <sys/ioctl.h>
#endif
#if defined(FF_HAVE_DRM) && defined(__aarch64__)
// https://github.com/alyssarosenzweig/linux/blob/agx-uapi-v7/include/uapi/drm/asahi_drm.h
// Found in kernel-headers-6.14.4-400.asahi.fc42.aarch64
#if __has_include(<drm/asahi_drm.h>)
#include <drm/asahi_drm.h>
#else
#include "asahi_drm.h"
#endif
#define FF_HAVE_DRM_ASAHI 1
// https://github.com/alyssarosenzweig/linux/blob/agx-uapi-v7/include/uapi/drm/asahi_drm.h
// Found in kernel-headers-6.14.4-400.asahi.fc42.aarch64
# if __has_include(<drm/asahi_drm.h>)
# include <drm/asahi_drm.h>
# else
# include "asahi_drm.h"
# endif
# define FF_HAVE_DRM_ASAHI 1
#endif
static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey)
{
static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey) {
uint32_t pciDirLength = pciDir->length;
ffStrbufAppendS(pciDir, "/driver");
char pathBuf[PATH_MAX];
ssize_t resultLength = readlink(pciDir->chars, pathBuf, ARRAY_SIZE(pathBuf));
if(resultLength <= 0) return false;
if (resultLength <= 0) {
return false;
}
const char* slash = memrchr(pathBuf, '/', (size_t) resultLength);
if (slash)
{
if (slash) {
slash++;
ffStrbufSetNS(result, (uint32_t) (resultLength - (slash - pathBuf)), slash);
}
if (ffStrbufEqualS(result, "nvidia"))
{
if (ffReadFileBuffer("/proc/driver/nvidia/version", buffer))
{
if (ffStrbufContainS(buffer, " Open "))
if (ffStrbufEqualS(result, "nvidia")) {
if (ffReadFileBuffer("/proc/driver/nvidia/version", buffer)) {
if (ffStrbufContainS(buffer, " Open ")) {
ffStrbufAppendS(result, " (open source)");
else
} else {
ffStrbufAppendS(result, " (proprietary)");
}
}
}
if (instance.config.general.detectVersion)
{
if (instance.config.general.detectVersion) {
ffStrbufAppendS(pciDir, "/module/version");
if (ffReadFileBuffer(pciDir->chars, buffer))
{
if (ffReadFileBuffer(pciDir->chars, buffer)) {
ffStrbufTrimRightSpace(buffer);
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, buffer);
}
else if (ffStrbufEqualS(result, "zx"))
{
} else if (ffStrbufEqualS(result, "zx")) {
ffStrbufSubstrBefore(pciDir, pciDirLength);
ffStrbufAppendS(pciDir, "/zx_info/driver_version");
if (ffReadFileBuffer(pciDir->chars, buffer))
{
if (ffReadFileBuffer(pciDir->chars, buffer)) {
ffStrbufTrimRightSpace(buffer);
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, buffer);
@@ -86,18 +80,17 @@ static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer
return true;
}
FF_MAYBE_UNUSED static const char* drmFindRenderFromCard(const char* drmCardKey, FFstrbuf* result)
{
FF_MAYBE_UNUSED static const char* drmFindRenderFromCard(const char* drmCardKey, FFstrbuf* result) {
char path[PATH_MAX];
sprintf(path, "/sys/class/drm/%s/device/drm", drmCardKey);
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path);
if (!dirp) return "Failed to open `/sys/class/drm/{drmCardKey}/device/drm`";
if (!dirp) {
return "Failed to open `/sys/class/drm/{drmCardKey}/device/drm`";
}
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (ffStrStartsWith(entry->d_name, "render"))
{
while ((entry = readdir(dirp)) != NULL) {
if (ffStrStartsWith(entry->d_name, "render")) {
ffStrbufSetS(result, "/dev/dri/");
ffStrbufAppendS(result, entry->d_name);
return NULL;
@@ -106,137 +99,142 @@ FF_MAYBE_UNUSED static const char* drmFindRenderFromCard(const char* drmCardKey,
return "Failed to find render device";
}
static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
{
#if FF_HAVE_DRM
static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) {
#if FF_HAVE_DRM
const char* error = drmFindRenderFromCard(drmKey, buffer);
if (error) return error;
if (ffStrbufEqualS(&gpu->driver, "radeon"))
if (error) {
return error;
}
if (ffStrbufEqualS(&gpu->driver, "radeon")) {
return ffDrmDetectRadeon(options, gpu, buffer->chars);
else
{
#if FF_HAVE_DRM_AMDGPU
} else {
# if FF_HAVE_DRM_AMDGPU
return ffDrmDetectAmdgpu(options, gpu, buffer->chars);
#else
# else
FF_UNUSED(options, gpu, drmKey, buffer);
return "Fastfetch is not compiled with libdrm_amdgpu support";
#endif
# endif
}
#else
#else
FF_UNUSED(options, gpu, drmKey, buffer);
return "Fastfetch is not compiled with drm support";
#endif
#endif
}
static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) {
// https://www.kernel.org/doc/html/v5.10/gpu/amdgpu.html#mem-info-vis-vram-total
const uint32_t pciDirLen = pciDir->length;
ffStrbufAppendS(pciDir, "/hwmon/");
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
if (!dirp) return;
if (!dirp) {
return;
}
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
break;
}
if (!entry) return;
if (!entry) {
return;
}
ffStrbufAppendS(pciDir, entry->d_name);
ffStrbufAppendC(pciDir, '/');
const uint32_t hwmonLen = pciDir->length;
uint64_t value = 0;
if (options->temp)
{
if (options->temp) {
ffStrbufAppendS(pciDir, "temp1_input"); // The on die GPU temperature in millidegrees Celsius
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0))) {
gpu->temperature = (double) value / 1000;
}
}
if (ffStrbufEqualS(&gpu->driver, "amdgpu")) // Ancient radeon drivers don't have these files
{
ffStrbufSubstrBefore(pciDir, hwmonLen);
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
if (ffPathExists(pciDir->chars, FF_PATHTYPE_ANY))
if (ffPathExists(pciDir->chars, FF_PATHTYPE_ANY)) {
gpu->type = FF_GPU_TYPE_INTEGRATED;
else
} else {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
if (options->driverSpecific)
{
if (options->driverSpecific) {
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
{
if (gpu->type == FF_GPU_TYPE_DISCRETE)
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0))) {
if (gpu->type == FF_GPU_TYPE_DISCRETE) {
gpu->dedicated.total = value;
else
} else {
gpu->shared.total = value;
}
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
{
if (gpu->type == FF_GPU_TYPE_DISCRETE)
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0))) {
if (gpu->type == FF_GPU_TYPE_DISCRETE) {
gpu->dedicated.used = value;
else
} else {
gpu->shared.used = value;
}
}
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/gpu_busy_percent");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0))) {
gpu->coreUsage = (double) value;
}
}
}
}
static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey)
{
static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey) {
// Works for Intel GPUs
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
// 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;
if (!drmKey) return;
if (!drmKey) {
return;
}
const uint32_t pciDirLen = pciDir->length;
bool isXE = ffStrbufEqualS(&gpu->driver, "xe");
if (isXE)
if (isXE) {
ffStrbufAppendS(pciDir, "/tile0/gt0/freq0/max_freq");
else
} else {
ffStrbufAppendF(pciDir, "/drm/%s/gt_max_freq_mhz", drmKey);
if (ffReadFileBuffer(pciDir->chars, buffer))
}
if (ffReadFileBuffer(pciDir->chars, buffer)) {
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0);
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
if (options->temp)
{
if (options->temp) {
ffStrbufAppendS(pciDir, "/hwmon/");
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
if (dirp)
{
if (dirp) {
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
ffStrbufSubstrBefore(pciDir, pciDirLen + strlen("/hwmon/"));
ffStrbufAppendS(pciDir, entry->d_name);
// https://github.com/Syllo/nvtop/blob/73291884d926445e499d6b9b71cb7a9bdbc7c393/src/extract_gpuinfo_intel.c#L279-L281
ffStrbufAppendS(pciDir, isXE ? "/temp2_input" : "/temp1_input");
if (ffReadFileBuffer(pciDir->chars, buffer))
{
if (ffReadFileBuffer(pciDir->chars, buffer)) {
uint64_t value = ffStrbufToUInt(buffer, 0);
if (value > 0)
{
if (value > 0) {
gpu->temperature = (double) value / 1000;
break;
}
@@ -247,44 +245,45 @@ static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu
}
}
static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
{
#if FF_HAVE_DRM
static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) {
#if FF_HAVE_DRM
ffStrbufSetS(buffer, "/dev/dri/");
ffStrbufAppendS(buffer, drmKey);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "Failed to open drm device";
if (fd < 0) {
return "Failed to open drm device";
}
if (ffStrbufEqualS(&gpu->driver, "xe"))
if (ffStrbufEqualS(&gpu->driver, "xe")) {
return ffDrmDetectXe(gpu, fd);
else if (ffStrbufEqualS(&gpu->driver, "i915"))
} else if (ffStrbufEqualS(&gpu->driver, "i915")) {
return ffDrmDetectI915(gpu, fd);
}
return "Unknown Intel GPU driver";
#else
#else
FF_UNUSED(gpu, drmKey, buffer);
return "Fastfetch is not compiled with drm support";
#endif
#endif
}
static const char* pciDetectTempGeneral(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
if (options->temp)
{
static const char* pciDetectTempGeneral(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) {
if (options->temp) {
const uint32_t pciDirLen = pciDir->length;
ffStrbufAppendS(pciDir, "/hwmon/");
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
if (dirp)
{
if (dirp) {
struct dirent* entry;
while ((entry = readdir(dirp)))
{
if (entry->d_name[0] == '.') continue;
while ((entry = readdir(dirp))) {
if (entry->d_name[0] == '.') {
continue;
}
ffStrbufAppendS(pciDir, entry->d_name);
ffStrbufAppendS(pciDir, "/temp1_input");
if (ffReadFileBuffer(pciDir->chars, buffer))
{
if (ffReadFileBuffer(pciDir->chars, buffer)) {
uint64_t value = ffStrbufToUInt(buffer, 0);
if (value > 0) gpu->temperature = (double) value / 1000.0;
if (value > 0) {
gpu->temperature = (double) value / 1000.0;
}
}
break;
}
@@ -294,54 +293,55 @@ static const char* pciDetectTempGeneral(const FFGPUOptions* options, FFGPUResult
return NULL;
}
static const char* drmDetectNouveauSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
{
#if FF_HAVE_DRM
static const char* drmDetectNouveauSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) {
#if FF_HAVE_DRM
ffStrbufSetS(buffer, "/dev/dri/");
ffStrbufAppendS(buffer, drmKey);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "Failed to open drm device";
if (fd < 0) {
return "Failed to open drm device";
}
return ffDrmDetectNouveau(gpu, fd);
#else
#else
FF_UNUSED(gpu, drmKey, buffer);
return "Fastfetch is not compiled with drm support";
#endif
#endif
}
static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) {
gpu->type = FF_GPU_TYPE_INTEGRATED;
const uint32_t pciDirLen = pciDir->length;
ffStrbufAppendS(pciDir, "/zx_info/eclk");
if (ffReadFileBuffer(pciDir->chars, buffer))
if (ffReadFileBuffer(pciDir->chars, buffer)) {
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, FF_GPU_FREQUENCY_UNSET);
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
if (options->driverSpecific)
{
if (options->driverSpecific) {
ffStrbufAppendS(pciDir, "/zx_info/engine_3d_usage");
if (ffReadFileBuffer(pciDir->chars, buffer))
if (ffReadFileBuffer(pciDir->chars, buffer)) {
gpu->coreUsage = ffStrbufToDouble(buffer, FF_GPU_CORE_USAGE_UNSET);
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/zx_info/fb_size");
if (ffReadFileBuffer(pciDir->chars, buffer))
if (ffReadFileBuffer(pciDir->chars, buffer)) {
gpu->shared.total = ffStrbufToUInt(buffer, FF_GPU_VMEM_SIZE_UNSET);
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET)
{
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) {
gpu->shared.total *= 1024 * 1024;
ffStrbufAppendS(pciDir, "/zx_info/free_fb_mem");
if (ffReadFileBuffer(pciDir->chars, buffer))
if (ffReadFileBuffer(pciDir->chars, buffer)) {
gpu->shared.used = ffStrbufToUInt(buffer, FF_GPU_VMEM_SIZE_UNSET);
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET)
{
if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) {
gpu->shared.used *= 1024 * 1024;
gpu->shared.used = gpu->shared.total - gpu->shared.used;
}
@@ -351,46 +351,48 @@ static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult*
return NULL;
}
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey)
{
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey) {
const uint32_t drmDirPathLength = deviceDir->length;
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
uint8_t classId, subclassId;
if (sscanf(buffer->chars + strlen("pci:"), "v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6)
if (sscanf(buffer->chars + strlen("pci:"), "v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6) {
return "Failed to parse pci modalias";
}
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) {
return "Not a GPU device";
}
char pciPath[PATH_MAX];
const char* pPciPath = NULL;
if (drmKey)
{
if (drmKey) {
ssize_t pathLength = readlink(deviceDir->chars, pciPath, ARRAY_SIZE(pciPath) - 1);
if (pathLength <= 0)
if (pathLength <= 0) {
return "Unable to get PCI device path";
}
pciPath[pathLength] = '\0';
pPciPath = strrchr(pciPath, '/');
if (__builtin_expect(pPciPath != NULL, true))
if (__builtin_expect(pPciPath != NULL, true)) {
pPciPath++;
else
} else {
pPciPath = pciPath;
}
else
{
}
} else {
pPciPath = memrchr(deviceDir->chars, '/', deviceDir->length);
assert(pPciPath);
pPciPath++;
}
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4) {
return "Invalid PCI device path";
}
if (pciFunc > 0 && subclassId == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
if (pciFunc > 0 && subclassId == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) {
return "Likely an auxiliary display controller"; // #2034
}
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString((uint16_t) vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
@@ -406,17 +408,13 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
char drmKeyBuffer[8];
if (!drmKey)
{
if (!drmKey) {
ffStrbufAppendS(deviceDir, "/drm");
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(deviceDir->chars);
if (dirp)
{
if (dirp) {
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (ffStrStartsWith(entry->d_name, "card"))
{
while ((entry = readdir(dirp)) != NULL) {
if (ffStrStartsWith(entry->d_name, "card")) {
ffStrCopy(drmKeyBuffer, entry->d_name, ARRAY_SIZE(drmKeyBuffer));
drmKey = drmKeyBuffer;
break;
@@ -426,77 +424,71 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
}
if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey);
if (drmKey) {
ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey);
}
pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey);
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
bool ok = false;
if (drmKey && options->driverSpecific)
if (drmKey && options->driverSpecific) {
ok = drmDetectAmdSpecific(options, gpu, drmKey, buffer) == NULL;
}
if (!ok)
{
if (!ok) {
pciDetectAmdSpecific(options, gpu, deviceDir, buffer);
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
ffStrbufAppendS(deviceDir, "/revision");
if (ffReadFileBuffer(deviceDir->chars, buffer))
{
if (ffReadFileBuffer(deviceDir->chars, buffer)) {
char* pend;
uint64_t revision = strtoul(buffer->chars, &pend, 16);
if (pend != buffer->chars)
if (pend != buffer->chars) {
ffGPUQueryAmdGpuName((uint16_t) deviceId, (uint8_t) revision, gpu);
}
}
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
}
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) {
pciDetectIntelSpecific(options, gpu, deviceDir, buffer, drmKey);
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
if (options->driverSpecific && drmKey)
if (options->driverSpecific && drmKey) {
drmDetectIntelSpecific(gpu, drmKey, buffer);
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && ffStrbufEqualS(&gpu->driver, "nouveau"))
{
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && ffStrbufEqualS(&gpu->driver, "nouveau")) {
pciDetectTempGeneral(options, gpu, deviceDir, buffer);
if (options->driverSpecific && drmKey)
if (options->driverSpecific && drmKey) {
drmDetectNouveauSpecific(gpu, drmKey, buffer);
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_ZHAOXIN && ffStrbufStartsWithS(&gpu->driver, "zx"))
{
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_ZHAOXIN && ffStrbufStartsWithS(&gpu->driver, "zx")) {
pciDetectTempGeneral(options, gpu, deviceDir, buffer);
pciDetectZxSpecific(options, gpu, deviceDir, buffer);
}
else
{
} else {
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
.domain = pciDomain,
.bus = pciBus,
.device = pciDevice,
.func = pciFunc,
});
.domain = pciDomain,
.bus = pciBus,
.device = pciDevice,
.func = pciFunc,
});
}
if (gpu->name.length == 0)
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
}
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
if (gpu->type == FF_GPU_TYPE_UNKNOWN) {
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
}
}
@@ -505,38 +497,38 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
#if __aarch64__
FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const char* name, FF_MAYBE_UNUSED FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey)
{
if (sscanf(name, "agx-t%lu", &gpu->deviceId) == 1)
FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const char* name, FF_MAYBE_UNUSED FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey) {
if (sscanf(name, "agx-t%lu", &gpu->deviceId) == 1) {
ffStrbufSetStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId));
}
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
#if FF_HAVE_DRM_ASAHI
# if FF_HAVE_DRM_ASAHI
ffStrbufSetS(buffer, "/dev/dri/");
ffStrbufAppendS(buffer, drmKey);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
if (fd >= 0)
if (fd >= 0) {
return ffDrmDetectAsahi(gpu, fd);
#endif
}
# endif
return NULL;
}
#endif
static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey)
{
static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey) {
char compatible[256]; // vendor,model-name
if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%255[^C]", compatible) != 1)
if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%255[^C]", compatible) != 1) {
return "Failed to parse of modalias or not a GPU device";
}
char* name = strchr(compatible, ',');
if (name)
{
if (name) {
*name = '\0';
++name;
}
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->deviceId = 0;
ffStrbufInit(&gpu->name);
@@ -553,22 +545,20 @@ static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, co
pciDetectDriver(&gpu->driver, drmDir, buffer, drmKey);
#ifdef __aarch64__
if (ffStrbufEqualS(&gpu->driver, "asahi"))
#ifdef __aarch64__
if (ffStrbufEqualS(&gpu->driver, "asahi")) {
drmDetectAsahiSpecific(gpu, name, buffer, drmKey);
#endif
}
#endif
if (!gpu->name.length)
{
if (!gpu->name.length) {
ffStrbufSetS(&gpu->name, name ?: compatible);
ffStrbufTrimRightSpace(&gpu->name);
}
if (!gpu->vendor.length && name)
{
if (ffStrEquals(compatible, "brcm"))
if (!gpu->vendor.length && name) {
if (ffStrEquals(compatible, "brcm")) {
ffStrbufSetStatic(&gpu->vendor, "Broadcom"); // Raspberry Pi
else
{
} else {
ffStrbufSetS(&gpu->vendor, compatible);
gpu->vendor.chars[0] = (char) toupper(compatible[0]);
}
@@ -577,36 +567,38 @@ static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, co
return NULL;
}
static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
{
static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus) {
FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64);
ffStrbufAppendS(&drmDir, "/sys/class/drm/");
const uint32_t drmDirLength = drmDir.length;
FF_AUTO_CLOSE_DIR DIR* dir = opendir(drmDir.chars);
if(dir == NULL)
if (dir == NULL) {
return "Failed to open `/sys/class/drm/`";
}
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
while ((entry = readdir(dir)) != NULL) {
if (!ffStrStartsWith(entry->d_name, "card") ||
strchr(entry->d_name + 4, '-') != NULL)
strchr(entry->d_name + 4, '-') != NULL) {
continue;
}
ffStrbufAppendS(&drmDir, entry->d_name);
ffStrbufAppendS(&drmDir, "/device/modalias");
if (!ffReadFileBuffer(drmDir.chars, &buffer))
if (!ffReadFileBuffer(drmDir.chars, &buffer)) {
continue;
}
ffStrbufSubstrBefore(&drmDir, drmDir.length - (uint32_t) strlen("/modalias"));
if (ffStrbufStartsWithS(&buffer, "pci:"))
if (ffStrbufStartsWithS(&buffer, "pci:")) {
detectPci(options, gpus, &buffer, &drmDir, entry->d_name);
else if (ffStrbufStartsWithS(&buffer, "of:")) // Open Firmware
} else if (ffStrbufStartsWithS(&buffer, "of:")) { // Open Firmware
detectOf(gpus, &buffer, &drmDir, entry->d_name);
}
ffStrbufSubstrBefore(&drmDir, drmDirLength);
}
@@ -614,15 +606,14 @@ static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
return NULL;
}
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
{
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus) {
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
const char* pciDirPath = "/sys/bus/pci/devices/";
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDirPath);
if(dirp == NULL)
if (dirp == NULL) {
return "Failed to open `/sys/bus/pci/devices/`";
}
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
ffStrbufAppendS(&pciDir, pciDirPath);
@@ -632,18 +623,19 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
ffStrbufAppendS(&pciDir, entry->d_name);
const uint32_t pciDevDirLength = pciDir.length;
ffStrbufAppendS(&pciDir, "/modalias");
if (!ffReadFileBuffer(pciDir.chars, &buffer))
if (!ffReadFileBuffer(pciDir.chars, &buffer)) {
continue;
}
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
assert(ffStrbufStartsWithS(&buffer, "pci:"));
@@ -654,18 +646,18 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
return NULL;
}
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
#if __x86_64__ || __aarch64__
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
#if __x86_64__ || __aarch64__
const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus);
if (ffGPUDetectWsl2(options, gpus) == NULL)
if (ffGPUDetectWsl2(options, gpus) == NULL) {
return NULL;
#endif
}
#endif
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
{
if (drmDetectGPUs(options, gpus) == NULL && gpus->length > 0)
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO) {
if (drmDetectGPUs(options, gpus) == NULL && gpus->length > 0) {
return NULL;
}
}
return pciDetectGPUs(options, gpus);
}
+68 -77
View File
@@ -3,8 +3,7 @@
#include "common/library.h"
#include "mtml.h"
struct FFMtmlData
{
struct FFMtmlData {
FF_LIBRARY_SYMBOL(mtmlDeviceCountGpuCores)
FF_LIBRARY_SYMBOL(mtmlDeviceGetBrand)
FF_LIBRARY_SYMBOL(mtmlDeviceGetIndex)
@@ -26,21 +25,18 @@ struct FFMtmlData
FF_LIBRARY_SYMBOL(mtmlLibraryShutDown)
bool inited;
MtmlLibrary *lib;
MtmlSystem *sys;
MtmlLibrary* lib;
MtmlSystem* sys;
} mtmlData;
FF_MAYBE_UNUSED static void shutdownMtml(void)
{
FF_MAYBE_UNUSED static void shutdownMtml(void) {
mtmlData.ffmtmlLibraryShutDown(mtmlData.lib);
}
const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDriverResult result, const char *soName)
{
const char* ffDetectMthreadsGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) {
#ifndef FF_DISABLE_DLOPEN
if (!mtmlData.inited)
{
if (!mtmlData.inited) {
mtmlData.inited = true;
FF_LIBRARY_LOAD(libmtml, "dlopen mtml failed", soName, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libmtml, mtmlLibraryInit)
@@ -64,13 +60,11 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUtilization)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryShutDown)
if (ffmtmlLibraryInit(&mtmlData.lib) != MTML_SUCCESS)
{
if (ffmtmlLibraryInit(&mtmlData.lib) != MTML_SUCCESS) {
mtmlData.ffmtmlLibraryInitSystem = NULL;
return "mtmlLibraryInit failed";
}
if (mtmlData.ffmtmlLibraryInitSystem(mtmlData.lib, &mtmlData.sys) != MTML_SUCCESS)
{
if (mtmlData.ffmtmlLibraryInitSystem(mtmlData.lib, &mtmlData.sys) != MTML_SUCCESS) {
mtmlData.ffmtmlLibraryShutDown(mtmlData.lib);
mtmlData.ffmtmlLibraryInitSystem = NULL;
return "mtmlLibraryInitSystem failed";
@@ -79,124 +73,121 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive
libmtml = NULL; // don't close mtml
}
if (mtmlData.ffmtmlLibraryInitSystem == NULL)
if (mtmlData.ffmtmlLibraryInitSystem == NULL) {
return "loading mtml library failed";
}
MtmlDevice *device = NULL;
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
{
MtmlDevice* device = NULL;
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) {
char pciBusIdStr[32];
snprintf(pciBusIdStr, ARRAY_SIZE(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
MtmlReturn ret = mtmlData.ffmtmlLibraryInitDeviceByPciSbdf(mtmlData.lib, pciBusIdStr, &device);
if (ret != MTML_SUCCESS)
if (ret != MTML_SUCCESS) {
return "mtmlLibraryInitDeviceByPciSbdf() failed";
}
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID)
{
}
} else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID) {
uint32_t count;
if (mtmlData.ffmtmlLibraryCountDevice(mtmlData.lib, &count) != MTML_SUCCESS)
if (mtmlData.ffmtmlLibraryCountDevice(mtmlData.lib, &count) != MTML_SUCCESS) {
return "mtmlLibraryCountDevice() failed";
}
for (uint32_t i = 0; i < count; i++, device = NULL)
{
if (mtmlData.ffmtmlLibraryInitDeviceByIndex(mtmlData.lib, i, &device) != MTML_SUCCESS)
for (uint32_t i = 0; i < count; i++, device = NULL) {
if (mtmlData.ffmtmlLibraryInitDeviceByIndex(mtmlData.lib, i, &device) != MTML_SUCCESS) {
continue;
}
MtmlPciInfo pciInfo;
if (mtmlData.ffmtmlDeviceGetPciInfo(device, &pciInfo) != MTML_SUCCESS)
if (mtmlData.ffmtmlDeviceGetPciInfo(device, &pciInfo) != MTML_SUCCESS) {
continue;
}
if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) ||
pciInfo.pciSubsystemId != cond->pciDeviceId.subSystemId)
pciInfo.pciSubsystemId != cond->pciDeviceId.subSystemId) {
continue;
}
break;
}
if (!device)
if (!device) {
return "Device not found";
}
else
{
}
} else {
return "Unknown condition type";
}
MtmlBrandType brand;
if (mtmlData.ffmtmlDeviceGetBrand(device, &brand) == MTML_SUCCESS)
{
switch (brand)
{
case MTML_BRAND_MTT:
*result.type = FF_GPU_TYPE_DISCRETE;
break;
default:
break;
if (mtmlData.ffmtmlDeviceGetBrand(device, &brand) == MTML_SUCCESS) {
switch (brand) {
case MTML_BRAND_MTT:
*result.type = FF_GPU_TYPE_DISCRETE;
break;
default:
break;
}
}
if (result.index)
{
if (result.index) {
unsigned int value;
if (mtmlData.ffmtmlDeviceGetIndex(device, &value) == MTML_SUCCESS)
if (mtmlData.ffmtmlDeviceGetIndex(device, &value) == MTML_SUCCESS) {
*result.index = value;
}
if (result.temp)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
uint32_t value;
if (mtmlData.ffmtmlGpuGetTemperature(gpu, &value) == MTML_SUCCESS)
*result.temp = value;
}
}
if (result.memory)
{
MtmlMemory *mem = NULL;
if (mtmlData.ffmtmlDeviceInitMemory(device, &mem) == MTML_SUCCESS)
{
if (result.temp) {
MtmlGpu* gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) {
uint32_t value;
if (mtmlData.ffmtmlGpuGetTemperature(gpu, &value) == MTML_SUCCESS) {
*result.temp = value;
}
}
}
if (result.memory) {
MtmlMemory* mem = NULL;
if (mtmlData.ffmtmlDeviceInitMemory(device, &mem) == MTML_SUCCESS) {
unsigned long long total;
if (mtmlData.ffmtmlMemoryGetTotal(mem, &total) == MTML_SUCCESS)
if (mtmlData.ffmtmlMemoryGetTotal(mem, &total) == MTML_SUCCESS) {
result.memory->total = total;
}
unsigned long long used;
if (mtmlData.ffmtmlMemoryGetUsed(mem, &used) == MTML_SUCCESS)
if (mtmlData.ffmtmlMemoryGetUsed(mem, &used) == MTML_SUCCESS) {
result.memory->used = used;
}
}
}
if (result.coreCount)
if (result.coreCount) {
mtmlData.ffmtmlDeviceCountGpuCores(device, result.coreCount);
}
if (result.frequency)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
if (result.frequency) {
MtmlGpu* gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) {
uint32_t clockMHz;
if (mtmlData.ffmtmlGpuGetMaxClock(gpu, &clockMHz) == MTML_SUCCESS)
if (mtmlData.ffmtmlGpuGetMaxClock(gpu, &clockMHz) == MTML_SUCCESS) {
*result.frequency = clockMHz;
}
}
}
if (result.coreUsage)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
if (result.coreUsage) {
MtmlGpu* gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) {
unsigned int utilization;
if (mtmlData.ffmtmlGpuGetUtilization(gpu, &utilization) == MTML_SUCCESS)
if (mtmlData.ffmtmlGpuGetUtilization(gpu, &utilization) == MTML_SUCCESS) {
*result.coreUsage = utilization;
}
}
}
if (result.name)
{
if (result.name) {
char name[MTML_DEVICE_NAME_BUFFER_SIZE];
if (mtmlData.ffmtmlDeviceGetName(device, name, ARRAY_SIZE(name)) == MTML_SUCCESS)
if (mtmlData.ffmtmlDeviceGetName(device, name, ARRAY_SIZE(name)) == MTML_SUCCESS) {
ffStrbufSetS(result.name, name);
}
}
return NULL;
+35 -28
View File
@@ -8,8 +8,7 @@
#include <dev/pci/pcidevs.h>
#include <dev/pci/pciio.h>
static inline int pciReadConf(int fd, uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint32_t* result)
{
static inline int pciReadConf(int fd, uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint32_t* result) {
struct pciio_bdf_cfgreg bdfr = {
.bus = bus,
.device = device,
@@ -19,67 +18,72 @@ static inline int pciReadConf(int fd, uint32_t bus, uint32_t device, uint32_t fu
},
};
if (ioctl(fd, PCI_IOC_BDF_CFGREAD, &bdfr) == -1)
if (ioctl(fd, PCI_IOC_BDF_CFGREAD, &bdfr) == -1) {
return -1;
}
*result = bdfr.cfgreg.val;
return 0;
}
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) {
char pciDevPath[] = "/dev/pciXXX";
for (uint32_t idev = 0; idev <= 255; idev++)
{
for (uint32_t idev = 0; idev <= 255; idev++) {
snprintf(pciDevPath + strlen("/dev/pci"), 4, "%u", idev);
FF_AUTO_CLOSE_FD int pcifd = open(pciDevPath, O_RDONLY | O_CLOEXEC);
if (pcifd < 0)
{
if (errno == ENOENT)
if (pcifd < 0) {
if (errno == ENOENT) {
break; // No more /dev/pciN devices
}
return "open(\"/dev/pciN\", O_RDONLY | O_CLOEXEC) failed";
}
struct pciio_businfo businfo;
if (ioctl(pcifd, PCI_IOC_BUSINFO, &businfo) != 0)
if (ioctl(pcifd, PCI_IOC_BUSINFO, &businfo) != 0) {
continue;
}
uint32_t bus = businfo.busno;
for (uint32_t dev = 0; dev < businfo.maxdevs; dev++)
{
for (uint32_t dev = 0; dev < businfo.maxdevs; dev++) {
uint32_t maxfuncs = 0;
for (uint32_t func = 0; func <= maxfuncs; func++)
{
for (uint32_t func = 0; func <= maxfuncs; func++) {
uint32_t pciid, pciclass;
if (pciReadConf(pcifd, bus, dev, func, PCI_ID_REG, &pciid) != 0)
if (pciReadConf(pcifd, bus, dev, func, PCI_ID_REG, &pciid) != 0) {
continue;
}
if (PCI_VENDOR(pciid) == PCI_VENDOR_INVALID || PCI_VENDOR(pciid) == 0)
if (PCI_VENDOR(pciid) == PCI_VENDOR_INVALID || PCI_VENDOR(pciid) == 0) {
continue;
}
if (pciReadConf(pcifd, bus, dev, func, PCI_CLASS_REG, &pciclass) != 0)
if (pciReadConf(pcifd, bus, dev, func, PCI_CLASS_REG, &pciclass) != 0) {
continue;
}
if (func == 0)
{
if (func == 0) {
// For some reason, pciReadConf returns success even for non-existing devices.
// So we need to check for `PCI_VENDOR(pciid) == PCI_VENDOR_INVALID` above to filter them out.
uint32_t bhlcr;
if (pciReadConf(pcifd, bus, dev, 0, PCI_BHLC_REG, &bhlcr) != 0)
if (pciReadConf(pcifd, bus, dev, 0, PCI_BHLC_REG, &bhlcr) != 0) {
continue;
}
if (PCI_HDRTYPE_MULTIFN(bhlcr)) maxfuncs = 7;
if (PCI_HDRTYPE_MULTIFN(bhlcr)) {
maxfuncs = 7;
}
}
if (PCI_CLASS(pciclass) != PCI_CLASS_DISPLAY)
if (PCI_CLASS(pciclass) != PCI_CLASS_DISPLAY) {
continue;
}
if (func > 0 && PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_DISPLAY_MISC)
if (func > 0 && PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_DISPLAY_MISC) {
continue; // Likely an auxiliary display controller (#2034)
}
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(PCI_VENDOR(pciid)));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
@@ -94,17 +98,20 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
if (gpu->name.length == 0)
}
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(PCI_SUBCLASS(pciclass), PCI_VENDOR(pciid), PCI_PRODUCT(pciid), gpu);
}
struct pciio_drvname drvname = {
.device = dev,
.function = func,
};
if (ioctl(pcifd, PCI_IOC_DRVNAME, &drvname) == 0)
if (ioctl(pcifd, PCI_IOC_DRVNAME, &drvname) == 0) {
ffStrbufInitS(&gpu->driver, drvname.name);
}
}
}
}
+1 -2
View File
@@ -1,7 +1,6 @@
#include "gpu.h"
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) {
FF_UNUSED(options, gpus);
return "Not supported on this platform";
}
+83 -90
View File
@@ -23,7 +23,7 @@ struct FFNvmlData {
#if defined(_WIN32) && !defined(FF_DISABLE_DLOPEN)
#include "nvapi.h"
# include "nvapi.h"
struct FFNvapiData {
FF_LIBRARY_SYMBOL(nvapi_Unload)
@@ -34,33 +34,33 @@ struct FFNvapiData {
bool inited;
} nvapiData;
static const char* detectMoreByNvapi(FFGpuDriverResult* result)
{
if (!nvapiData.inited)
{
static const char* detectMoreByNvapi(FFGpuDriverResult* result) {
if (!nvapiData.inited) {
nvapiData.inited = true;
FF_LIBRARY_LOAD_MESSAGE(libnvapi,
#ifdef _WIN64
# ifdef _WIN64
"nvapi64.dll"
#else
# else
"nvapi.dll"
#endif
, 1);
# endif
,
1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvapi, nvapi_QueryInterface)
#define FF_NVAPI_INTERFACE(iName, iOffset) \
__typeof__(&iName) ff ## iName = ffnvapi_QueryInterface(iOffset); \
if (ff ## iName == NULL) return "nvapi_QueryInterface " #iName " failed";
# define FF_NVAPI_INTERFACE(iName, iOffset) \
__typeof__(&iName) ff##iName = ffnvapi_QueryInterface(iOffset); \
if (ff##iName == NULL) return "nvapi_QueryInterface " #iName " failed";
FF_NVAPI_INTERFACE(nvapi_Initialize, NVAPI_INTERFACE_OFFSET_INITIALIZE)
FF_NVAPI_INTERFACE(nvapi_Unload, NVAPI_INTERFACE_OFFSET_UNLOAD)
FF_NVAPI_INTERFACE(nvapi_EnumPhysicalGPUs, NVAPI_INTERFACE_OFFSET_ENUM_PHYSICAL_GPUS)
FF_NVAPI_INTERFACE(nvapi_GPU_GetRamType, NVAPI_INTERFACE_OFFSET_GPU_GET_RAM_TYPE)
FF_NVAPI_INTERFACE(nvapi_GPU_GetGPUType, NVAPI_INTERFACE_OFFSET_GPU_GET_GPU_TYPE)
#undef FF_NVAPI_INTERFACE
# undef FF_NVAPI_INTERFACE
if (ffnvapi_Initialize() < 0)
if (ffnvapi_Initialize() < 0) {
return "NvAPI_Initialize() failed";
}
nvapiData.ffnvapi_EnumPhysicalGPUs = ffnvapi_EnumPhysicalGPUs;
nvapiData.ffnvapi_GPU_GetRamType = ffnvapi_GPU_GetRamType;
@@ -71,32 +71,33 @@ static const char* detectMoreByNvapi(FFGpuDriverResult* result)
libnvapi = NULL; // don't close nvapi
}
if (nvapiData.ffnvapi_EnumPhysicalGPUs == NULL)
if (nvapiData.ffnvapi_EnumPhysicalGPUs == NULL) {
return "loading nvapi library failed";
}
NvPhysicalGpuHandle handles[32];
int gpuCount = 0;
if (nvapiData.ffnvapi_EnumPhysicalGPUs(handles, &gpuCount) < 0)
if (nvapiData.ffnvapi_EnumPhysicalGPUs(handles, &gpuCount) < 0) {
return "NvAPI_EnumPhysicalGPUs() failed";
}
uint32_t gpuIndex = *result->index;
if (gpuIndex >= (uint32_t) gpuCount)
if (gpuIndex >= (uint32_t) gpuCount) {
return "GPU index out of range";
}
// Not very sure. Need to check in multi-GPU system
NvPhysicalGpuHandle gpuHandle = handles[gpuIndex];
NvApiGPUMemoryType memType;
if (result->memoryType && nvapiData.ffnvapi_GPU_GetRamType(gpuHandle, &memType) == 0)
{
switch (memType)
{
#define FF_NVAPI_MEMORY_TYPE(type) \
case NVAPI_GPU_MEMORY_TYPE_##type: \
ffStrbufSetStatic(result->memoryType, #type); \
break;
if (result->memoryType && nvapiData.ffnvapi_GPU_GetRamType(gpuHandle, &memType) == 0) {
switch (memType) {
# define FF_NVAPI_MEMORY_TYPE(type) \
case NVAPI_GPU_MEMORY_TYPE_##type: \
ffStrbufSetStatic(result->memoryType, #type); \
break;
FF_NVAPI_MEMORY_TYPE(UNKNOWN)
FF_NVAPI_MEMORY_TYPE(SDRAM)
FF_NVAPI_MEMORY_TYPE(DDR1)
@@ -114,7 +115,7 @@ static const char* detectMoreByNvapi(FFGpuDriverResult* result)
FF_NVAPI_MEMORY_TYPE(GDDR6)
FF_NVAPI_MEMORY_TYPE(GDDR6X)
FF_NVAPI_MEMORY_TYPE(GDDR7)
#undef FF_NVAPI_MEMORY_TYPE
# undef FF_NVAPI_MEMORY_TYPE
default:
ffStrbufSetF(result->memoryType, "Unknown (%d)", memType);
break;
@@ -122,10 +123,8 @@ static const char* detectMoreByNvapi(FFGpuDriverResult* result)
}
NvApiGPUType gpuType;
if (result->type && nvapiData.ffnvapi_GPU_GetGPUType(gpuHandle, &gpuType) == 0)
{
switch (gpuType)
{
if (result->type && nvapiData.ffnvapi_GPU_GetGPUType(gpuHandle, &gpuType) == 0) {
switch (gpuType) {
case NV_SYSTEM_TYPE_IGPU:
*result->type = FF_GPU_TYPE_INTEGRATED;
break;
@@ -143,14 +142,12 @@ static const char* detectMoreByNvapi(FFGpuDriverResult* result)
#endif
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName)
{
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) {
#ifndef FF_DISABLE_DLOPEN
if (!nvmlData.inited)
{
if (!nvmlData.inited) {
nvmlData.inited = true;
FF_LIBRARY_LOAD(libnvml, "dlopen nvml failed", soName , 1);
FF_LIBRARY_LOAD(libnvml, "dlopen nvml failed", soName, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvml, nvmlInit_v2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvml, nvmlShutdown)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetCount_v2)
@@ -167,8 +164,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetIndex)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetName)
if (ffnvmlInit_v2() != NVML_SUCCESS)
{
if (ffnvmlInit_v2() != NVML_SUCCESS) {
nvmlData.ffnvmlDeviceGetNumGpuCores = NULL;
return "nvmlInit_v2() failed";
}
@@ -176,51 +172,52 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
libnvml = NULL; // don't close nvml
}
if (nvmlData.ffnvmlDeviceGetNumGpuCores == NULL)
if (nvmlData.ffnvmlDeviceGetNumGpuCores == NULL) {
return "loading nvml library failed";
}
nvmlDevice_t device = NULL;
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
{
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) {
char pciBusIdStr[32];
snprintf(pciBusIdStr, ARRAY_SIZE(pciBusIdStr), "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
nvmlReturn_t ret = nvmlData.ffnvmlDeviceGetHandleByPciBusId_v2(pciBusIdStr, &device);
if (ret != NVML_SUCCESS)
if (ret != NVML_SUCCESS) {
return "nvmlDeviceGetHandleByPciBusId_v2() failed";
}
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID)
{
}
} else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID) {
uint32_t count;
if (nvmlData.ffnvmlDeviceGetCount_v2(&count) != NVML_SUCCESS)
if (nvmlData.ffnvmlDeviceGetCount_v2(&count) != NVML_SUCCESS) {
return "nvmlDeviceGetCount_v2() failed";
}
for (uint32_t i = 0; i < count; i++, device = NULL)
{
if (nvmlData.ffnvmlDeviceGetHandleByIndex_v2(i, &device) != NVML_SUCCESS)
for (uint32_t i = 0; i < count; i++, device = NULL) {
if (nvmlData.ffnvmlDeviceGetHandleByIndex_v2(i, &device) != NVML_SUCCESS) {
continue;
}
nvmlPciInfo_t pciInfo;
if (nvmlData.ffnvmlDeviceGetPciInfo_v3(device, &pciInfo) != NVML_SUCCESS)
if (nvmlData.ffnvmlDeviceGetPciInfo_v3(device, &pciInfo) != NVML_SUCCESS) {
continue;
}
if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) ||
pciInfo.pciSubSystemId != cond->pciDeviceId.subSystemId)
pciInfo.pciSubSystemId != cond->pciDeviceId.subSystemId) {
continue;
}
break;
}
}
if (!device) return "Device not found";
if (!device) {
return "Device not found";
}
if (result.type)
{
if (result.type) {
nvmlBrandType_t brand;
if (nvmlData.ffnvmlDeviceGetBrand(device, &brand) == NVML_SUCCESS)
{
switch (brand)
{
if (nvmlData.ffnvmlDeviceGetBrand(device, &brand) == NVML_SUCCESS) {
switch (brand) {
case NVML_BRAND_NVIDIA_RTX:
case NVML_BRAND_QUADRO_RTX:
case NVML_BRAND_GEFORCE:
@@ -235,64 +232,60 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
}
}
if (result.index)
{
if (result.index) {
unsigned int value;
if (nvmlData.ffnvmlDeviceGetIndex(device, &value) == NVML_SUCCESS)
{
if (nvmlData.ffnvmlDeviceGetIndex(device, &value) == NVML_SUCCESS) {
*result.index = value;
#ifdef _WIN32
# ifdef _WIN32
// Don't bother loading nvapi for GPU type detection only
if (result.memoryType)
if (result.memoryType) {
detectMoreByNvapi(&result);
#endif
}
# endif
}
}
if (result.temp)
{
if (result.temp) {
uint32_t value;
if (nvmlData.ffnvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &value) == NVML_SUCCESS)
if (nvmlData.ffnvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &value) == NVML_SUCCESS) {
*result.temp = value;
}
}
if (result.memory)
{
nvmlMemory_v2_t memory = { .version = nvmlMemory_v2 };
if (nvmlData.ffnvmlDeviceGetMemoryInfo_v2(device, &memory) == NVML_SUCCESS)
{
if (result.memory) {
nvmlMemory_v2_t memory = {.version = nvmlMemory_v2};
if (nvmlData.ffnvmlDeviceGetMemoryInfo_v2(device, &memory) == NVML_SUCCESS) {
result.memory->total = memory.used + memory.free;
result.memory->used = memory.used;
}
else
{
} else {
nvmlMemory_t memory_v1;
if (nvmlData.ffnvmlDeviceGetMemoryInfo(device, &memory_v1) == NVML_SUCCESS)
{
if (nvmlData.ffnvmlDeviceGetMemoryInfo(device, &memory_v1) == NVML_SUCCESS) {
result.memory->total = memory_v1.total;
result.memory->used = memory_v1.used;
}
}
}
if (result.coreCount)
if (result.coreCount) {
nvmlData.ffnvmlDeviceGetNumGpuCores(device, result.coreCount);
if (result.frequency)
nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency);
if (result.coreUsage)
{
nvmlUtilization_t utilization;
if (nvmlData.ffnvmlDeviceGetUtilizationRates(device, &utilization) == NVML_SUCCESS)
*result.coreUsage = utilization.gpu;
}
if (result.name)
{
if (result.frequency) {
nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency);
}
if (result.coreUsage) {
nvmlUtilization_t utilization;
if (nvmlData.ffnvmlDeviceGetUtilizationRates(device, &utilization) == NVML_SUCCESS) {
*result.coreUsage = utilization.gpu;
}
}
if (result.name) {
char name[NVML_DEVICE_NAME_V2_BUFFER_SIZE];
if (nvmlData.ffnvmlDeviceGetName(device, name, ARRAY_SIZE(name)) == NVML_SUCCESS)
if (nvmlData.ffnvmlDeviceGetName(device, name, ARRAY_SIZE(name)) == NVML_SUCCESS) {
ffStrbufSetS(result.name, name);
}
}
return NULL;
+30 -24
View File
@@ -8,8 +8,7 @@
#include <dev/pci/pcidevs.h>
#include <sys/pciio.h>
static inline int pciReadConf(int fd, uint8_t bus, uint8_t device, uint8_t func, uint8_t reg, uint32_t* result)
{
static inline int pciReadConf(int fd, uint8_t bus, uint8_t device, uint8_t func, uint8_t reg, uint32_t* result) {
struct pci_io bdfr = {
.pi_sel = {
.pc_bus = bus,
@@ -20,55 +19,60 @@ static inline int pciReadConf(int fd, uint8_t bus, uint8_t device, uint8_t func,
.pi_width = 4,
};
if (ioctl(fd, PCIOCREAD, &bdfr) == -1)
if (ioctl(fd, PCIOCREAD, &bdfr) == -1) {
return -1;
}
*result = bdfr.pi_data;
return 0;
}
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) {
char pciDevPath[] = "/dev/pci0";
FF_AUTO_CLOSE_FD int pcifd = open(pciDevPath, O_RDONLY | O_CLOEXEC);
if (pcifd < 0)
if (pcifd < 0) {
return "open(\"/dev/pci0\", O_RDONLY | O_CLOEXEC) failed";
}
for (uint16_t bus = 0; bus <= 255; bus++)
{
for (uint8_t dev = 0; dev < 32; dev++)
{
for (uint16_t bus = 0; bus <= 255; bus++) {
for (uint8_t dev = 0; dev < 32; dev++) {
uint8_t maxfuncs = 0;
for (uint8_t func = 0; func <= maxfuncs; func++)
{
for (uint8_t func = 0; func <= maxfuncs; func++) {
uint32_t pciid, pciclass;
if (pciReadConf(pcifd, (uint8_t) bus, dev, func, PCI_ID_REG, &pciid) != 0)
if (pciReadConf(pcifd, (uint8_t) bus, dev, func, PCI_ID_REG, &pciid) != 0) {
continue;
}
if (PCI_VENDOR(pciid) == PCI_VENDOR_INVALID || PCI_VENDOR(pciid) == 0)
if (PCI_VENDOR(pciid) == PCI_VENDOR_INVALID || PCI_VENDOR(pciid) == 0) {
continue;
}
if (pciReadConf(pcifd, (uint8_t) bus, dev, func, PCI_CLASS_REG, &pciclass) != 0)
if (pciReadConf(pcifd, (uint8_t) bus, dev, func, PCI_CLASS_REG, &pciclass) != 0) {
continue;
}
if (func == 0)
{
if (func == 0) {
// For some reason, pciReadConf returns success even for non-existing devices.
// So we need to check for `PCI_VENDOR(pciid) == PCI_VENDOR_INVALID` above to filter them out.
uint32_t bhlcr;
if (pciReadConf(pcifd, (uint8_t) bus, dev, 0, PCI_BHLC_REG, &bhlcr) != 0)
if (pciReadConf(pcifd, (uint8_t) bus, dev, 0, PCI_BHLC_REG, &bhlcr) != 0) {
continue;
}
if (PCI_HDRTYPE_MULTIFN(bhlcr)) maxfuncs = 7;
if (PCI_HDRTYPE_MULTIFN(bhlcr)) {
maxfuncs = 7;
}
}
if (PCI_CLASS(pciclass) != PCI_CLASS_DISPLAY)
if (PCI_CLASS(pciclass) != PCI_CLASS_DISPLAY) {
continue;
}
if (func > 0 && PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_DISPLAY_MISC)
if (func > 0 && PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_DISPLAY_MISC) {
continue; // Likely an auxiliary display controller (#2034)
}
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(PCI_VENDOR(pciid)));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
@@ -83,10 +87,12 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
if (gpu->name.length == 0)
}
if (gpu->name.length == 0) {
ffGPUFillVendorAndName(PCI_SUBCLASS(pciclass), PCI_VENDOR(pciid), PCI_PRODUCT(pciid), gpu);
}
}
}
}
+112 -106
View File
@@ -5,131 +5,135 @@
#include <stdlib.h>
#ifdef __FreeBSD__
#include <paths.h>
#ifndef _PATH_LOCALBASE
#define _PATH_LOCALBASE "/usr/local"
#endif
# include <paths.h>
# ifndef _PATH_LOCALBASE
# define _PATH_LOCALBASE "/usr/local"
# endif
#elif __OpenBSD__
#define _PATH_LOCALBASE "/usr/local"
# define _PATH_LOCALBASE "/usr/local"
#elif __NetBSD__
#define _PATH_LOCALBASE "/usr/pkg"
# define _PATH_LOCALBASE "/usr/pkg"
#endif
#if FF_HAVE_EMBEDDED_PCIIDS
#include "fastfetch_pciids.c.inc"
# include "fastfetch_pciids.c.inc"
#endif
#if FF_HAVE_EMBEDDED_AMDGPUIDS
#include "fastfetch_amdgpuids.c.inc"
# include "fastfetch_amdgpuids.c.inc"
#endif
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
static const FFstrbuf* loadPciIds()
{
static const FFstrbuf* loadPciIds() {
static FFstrbuf pciids;
if (pciids.chars) return &pciids;
if (pciids.chars) {
return &pciids;
}
ffStrbufInit(&pciids);
#ifdef FF_CUSTOM_PCI_IDS_PATH
#ifdef FF_CUSTOM_PCI_IDS_PATH
ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), &pciids);
ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), &pciids);
#else // FF_CUSTOM_PCI_IDS_PATH
#else // FF_CUSTOM_PCI_IDS_PATH
#if __linux__
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", &pciids);
if (pciids.length == 0)
{
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", &pciids); // debian?
if (pciids.length == 0)
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", &pciids);
# if __linux__
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", &pciids);
if (pciids.length == 0) {
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", &pciids); // debian?
if (pciids.length == 0) {
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", &pciids);
}
#elif __OpenBSD__ || __FreeBSD__ || __NetBSD__
ffReadFileBuffer(_PATH_LOCALBASE "/share/hwdata/pci.ids", &pciids);
if (pciids.length == 0)
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids);
#elif __sun
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids);
#elif __HAIKU__
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/system/data/hwdata/pci.ids", &pciids);
#endif
}
# elif __OpenBSD__ || __FreeBSD__ || __NetBSD__
ffReadFileBuffer(_PATH_LOCALBASE "/share/hwdata/pci.ids", &pciids);
if (pciids.length == 0) {
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids);
}
# elif __sun
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids);
# elif __HAIKU__
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/system/data/hwdata/pci.ids", &pciids);
# endif
#endif // FF_CUSTOM_PCI_IDS_PATH
#endif // FF_CUSTOM_PCI_IDS_PATH
return &pciids;
}
static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
{
if (content->length)
{
static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) {
if (content->length) {
char buffer[32];
// Search for vendor
uint32_t len = (uint32_t) snprintf(buffer, ARRAY_SIZE(buffer), "\n%04x ", vendor);
char* start = (char*) memmem(content->chars, content->length, buffer, len);
char* end = content->chars + content->length;
if (start)
{
if (start) {
start += len;
end = memchr(start, '\n', (uint32_t) (end - start));
if (!end)
if (!end) {
end = content->chars + content->length;
if (!gpu->vendor.length)
}
if (!gpu->vendor.length) {
ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start);
}
start = end; // point to '\n' of vendor
start = end; // point to '\n' of vendor
end = start + 1; // point to start of devices
// find the start of next vendor
while (end[0] == '\t' || end[0] == '#')
{
while (end[0] == '\t' || end[0] == '#') {
end = strchr(end, '\n');
if (!end)
{
if (!end) {
end = content->chars + content->length;
break;
}
else
} else {
end++;
}
}
// Search for device
len = (uint32_t) snprintf(buffer, ARRAY_SIZE(buffer), "\n\t%04x ", device);
start = memmem(start, (size_t) (end - start), buffer, len);
if (start)
{
if (start) {
start += len;
end = memchr(start, '\n', (uint32_t) (end - start));
if (!end)
if (!end) {
end = content->chars + content->length;
}
char* closingBracket = end - 1;
if (*closingBracket == ']')
{
if (*closingBracket == ']') {
char* openingBracket = memrchr(start, '[', (size_t) (closingBracket - start));
if (openingBracket)
{
if (openingBracket) {
openingBracket++;
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
}
}
if (!gpu->name.length)
if (!gpu->name.length) {
ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start);
}
}
}
}
if (!gpu->name.length)
{
if (!gpu->name.length) {
const char* subclassStr;
switch (subclass)
{
case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break;
case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break;
case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break;
default: subclassStr = ""; break;
switch (subclass) {
case 0 /*PCI_CLASS_DISPLAY_VGA*/:
subclassStr = " (VGA compatible)";
break;
case 1 /*PCI_CLASS_DISPLAY_XGA*/:
subclassStr = " (XGA compatible)";
break;
case 2 /*PCI_CLASS_DISPLAY_3D*/:
subclassStr = " (3D)";
break;
default:
subclassStr = "";
break;
}
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr);
@@ -137,49 +141,53 @@ static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t
}
#if FF_HAVE_EMBEDDED_PCIIDS
static inline int pciDeviceCmp(const uint16_t* key, const FFPciDevice* element)
{
static inline int pciDeviceCmp(const uint16_t* key, const FFPciDevice* element) {
return (int) *key - (int) element->id;
}
static bool loadPciidsInc(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
{
for (const FFPciVendor* pvendor = ffPciVendors; pvendor->name; pvendor++)
{
if (pvendor->id != vendor) continue;
static bool loadPciidsInc(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) {
for (const FFPciVendor* pvendor = ffPciVendors; pvendor->name; pvendor++) {
if (pvendor->id != vendor) {
continue;
}
if (!gpu->vendor.length)
if (!gpu->vendor.length) {
ffStrbufSetS(&gpu->vendor, pvendor->name);
}
const FFPciDevice* pdevice = (const FFPciDevice*) bsearch(&device, pvendor->devices, pvendor->nDevices, sizeof(*pdevice), (void*) pciDeviceCmp);
if (pdevice)
{
if (pdevice) {
uint32_t nameLen = (uint32_t) strlen(pdevice->name);
const char* closingBracket = pdevice->name + nameLen - 1;
if (*closingBracket == ']')
{
if (*closingBracket == ']') {
const char* openingBracket = memrchr(pdevice->name, '[', nameLen - 1);
if (openingBracket)
{
if (openingBracket) {
openingBracket++;
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
}
}
if (!gpu->name.length)
if (!gpu->name.length) {
ffStrbufSetNS(&gpu->name, nameLen, pdevice->name);
}
return true;
}
if (!gpu->name.length)
{
if (!gpu->name.length) {
const char* subclassStr;
switch (subclass)
{
case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break;
case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break;
case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break;
default: subclassStr = ""; break;
switch (subclass) {
case 0 /*PCI_CLASS_DISPLAY_VGA*/:
subclassStr = " (VGA compatible)";
break;
case 1 /*PCI_CLASS_DISPLAY_XGA*/:
subclassStr = " (XGA compatible)";
break;
case 2 /*PCI_CLASS_DISPLAY_3D*/:
subclassStr = " (3D)";
break;
default:
subclassStr = "";
break;
}
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr);
@@ -190,28 +198,26 @@ static bool loadPciidsInc(uint8_t subclass, uint16_t vendor, uint16_t device, FF
}
#endif
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
{
#if FF_HAVE_EMBEDDED_PCIIDS
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) {
#if FF_HAVE_EMBEDDED_PCIIDS
bool ok = loadPciidsInc(subclass, vendor, device, gpu);
if (ok) return;
#endif
if (ok) {
return;
}
#endif
return parsePciIdsFile(loadPciIds(), subclass, vendor, device, gpu);
}
#if FF_HAVE_EMBEDDED_AMDGPUIDS
static inline int amdGpuCmp(const uint32_t* key, const FFArmGpuProduct* element)
{
static inline int amdGpuCmp(const uint32_t* key, const FFArmGpuProduct* element) {
// Maximum value of *key is 0x00FFFFFF. `(int) *key` should never overflow
return (int) *key - (int) element->id;
}
static bool loadAmdGpuIdsInc(uint16_t deviceId, uint8_t revision, FFGPUResult* gpu)
{
static bool loadAmdGpuIdsInc(uint16_t deviceId, uint8_t revision, FFGPUResult* gpu) {
uint32_t key = (deviceId << 8u) | revision;
FFArmGpuProduct* product = bsearch(&key, ffAmdGpuProducts, ARRAY_SIZE(ffAmdGpuProducts), sizeof(*ffAmdGpuProducts), (void*) amdGpuCmp);
if (product)
{
if (product) {
ffStrbufSetS(&gpu->name, product->name);
return true;
}
@@ -219,22 +225,22 @@ static bool loadAmdGpuIdsInc(uint16_t deviceId, uint8_t revision, FFGPUResult* g
}
#endif
static void parseAmdGpuIdsFile(uint16_t deviceId, uint8_t revision, FFGPUResult* gpu)
{
static void parseAmdGpuIdsFile(uint16_t deviceId, uint8_t revision, FFGPUResult* gpu) {
char query[32];
snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
#ifdef FF_CUSTOM_AMDGPU_IDS_PATH
#ifdef FF_CUSTOM_AMDGPU_IDS_PATH
ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name);
#else
#else
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
#endif
#endif
}
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu)
{
#if FF_HAVE_EMBEDDED_AMDGPUIDS
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu) {
#if FF_HAVE_EMBEDDED_AMDGPUIDS
bool ok = loadAmdGpuIdsInc(deviceId, revisionId, gpu);
if (ok) return;
#endif
if (ok) {
return;
}
#endif
return parseAmdGpuIdsFile(deviceId, revisionId, gpu);
}
+12 -15
View File
@@ -3,14 +3,11 @@
#include <libdevinfo.h>
static int walkDevTree(di_node_t node, FF_MAYBE_UNUSED di_minor_t minor, FFlist* gpus)
{
static int walkDevTree(di_node_t node, FF_MAYBE_UNUSED di_minor_t minor, FFlist* gpus) {
int* vendorId;
int* deviceId;
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "vendor-id", &vendorId) > 0
&& di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-id", &deviceId) > 0)
{
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "vendor-id", &vendorId) > 0 && di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-id", &deviceId) > 0) {
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitS(&gpu->vendor, ffGPUGetVendorString((uint16_t) *vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInitS(&gpu->driver, di_driver_name(node));
@@ -25,19 +22,19 @@ static int walkDevTree(di_node_t node, FF_MAYBE_UNUSED di_minor_t minor, FFlist*
gpu->deviceId = strtoul(di_bus_addr(node), NULL, 16);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
int* revId;
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "revision-id", &revId) > 0)
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "revision-id", &revId) > 0) {
ffGPUQueryAmdGpuName((uint16_t) *deviceId, (uint8_t) *revId, gpu);
}
}
if (gpu->name.length == 0)
{
if (gpu->name.length == 0) {
uint8_t subclass = 0; // assume VGA
int* classCode;
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "class-code", &classCode) > 0)
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "class-code", &classCode) > 0) {
subclass = (uint8_t) (*classCode & 0xFFFF);
}
ffGPUFillVendorAndName(subclass, (uint16_t) *vendorId, (uint16_t) *deviceId, gpu);
}
}
@@ -45,11 +42,11 @@ static int walkDevTree(di_node_t node, FF_MAYBE_UNUSED di_minor_t minor, FFlist*
return DI_WALK_CONTINUE;
}
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) {
di_node_t rootNode = di_init("/", DINFOCPYALL);
if (rootNode == DI_NODE_NIL)
if (rootNode == DI_NODE_NIL) {
return "di_init() failed";
}
di_walk_minor(rootNode, DDI_NT_DISPLAY, DI_WALK_CLDFIRST, gpus, (void*) walkDevTree);
di_fini(rootNode);
+110 -193
View File
@@ -20,20 +20,18 @@ const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\C
#define GUID_DEVCLASS_DISPLAY_STRING L"{4d36e968-e325-11ce-bfc1-08002be10318}" // Found in <devguid.h>
static inline void wrapRegCloseKey(HKEY* phKey)
{
if(*phKey)
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)
{
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)
{
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";
}
@@ -42,33 +40,30 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
FF_AUTO_FREE DEVINSTID_W devIdList = malloc(devIdListSize * sizeof(*devIdList));
if (CM_Get_Device_ID_ListW(GUID_DEVCLASS_DISPLAY_STRING, devIdList, devIdListSize, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT) != CR_SUCCESS)
{
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)
{
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)
{
if (CM_Locate_DevNodeW(&devInst, devId, CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS) {
FF_DEBUG("Failed to get device instance ID or locate device node");
continue;
}
FF_DEBUG("Device instance ID: %lu", devInst);
for (wchar_t* p = devId; *p; p++)
{
if (*p >= L'a' && *p <= L'z')
for (wchar_t* p = devId; *p; p++) {
if (*p >= L'a' && *p <= L'z') {
*p -= L'a' - L'A';
}
}
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
deviceCount++;
FF_DEBUG("Added GPU #%d to list", deviceCount);
@@ -87,37 +82,28 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
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)
{
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));
}
else
{
} else {
FF_DEBUG("Failed to parse PCI device information from instance ID");
}
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)
{
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)
{
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
{
} else {
FF_DEBUG("Failed to get PCI address");
}
}
else
{
} else {
FF_DEBUG("Failed to get PCI bus number");
}
@@ -130,164 +116,130 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
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)
{
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);
}
else
{
} else {
FF_DEBUG("Failed to get device description");
}
if (wcsncmp(devId, L"SWD\\", 4) == 0 || wcsncmp(devId, L"ROOT\\DISPLAY\\", 13) == 0)
{
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)
{
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))
{
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))
{
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) {
FF_DEBUG("Opened DirectX registry key");
if (gpu->vendor.length == 0)
{
if (gpu->vendor.length == 0) {
uint32_t vendorId = 0;
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
{
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)
{
if (gpu->name.length == 0) {
FF_DEBUG("Trying to get GPU name from DirectX registry");
if (ffRegReadStrbuf(hDirectxKey, L"Description", &gpu->name, NULL))
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))
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))
{
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))
{
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))
{
if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL)) {
FF_DEBUG("Found adapter LUID: %llu", adapterLuid);
if (!gpu->deviceId) gpu->deviceId = ffGPUGeneral2Id(adapterLuid);
if (!gpu->deviceId) {
gpu->deviceId = ffGPUGeneral2Id(adapterLuid);
}
}
uint32_t featureLevel = 0;
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
{
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)
{
} 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)
{
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
);
ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u", (unsigned) (driverVersion >> 48) & 0xFFFF, (unsigned) (driverVersion >> 32) & 0xFFFF, (unsigned) (driverVersion >> 16) & 0xFFFF, (unsigned) (driverVersion >> 0) & 0xFFFF);
}
}
else
{
} else {
FF_DEBUG("Failed to open DirectX registry key");
}
}
else
{
} else {
FF_DEBUG("Failed to get VideoID or invalid buffer length");
}
}
else
{
} 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)
{
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)
{
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))
{
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))
{
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"))
if (ffStrbufContainS(&gpu->vendor, "Intel")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if (ffStrbufContainS(&gpu->vendor, "NVIDIA"))
} else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
} 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))
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))
}
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))
{
}
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))
{
if (ffRegReadUint(hRegDriverKey, L"HardwareInformation.MemorySize", &memorySize, NULL)) {
gpu->dedicated.total = memorySize;
FF_DEBUG("Found memory size from hardware info: %u bytes", memorySize);
}
}
else
{
} else {
FF_DEBUG("Found qwMemorySize from hardware info: %llu bytes", gpu->dedicated.total);
}
}
}
else
{
} else {
FF_DEBUG("Failed to open driver registry key");
}
}
else
{
} else {
FF_DEBUG("Failed to get driver GUID or invalid buffer length");
}
}
@@ -295,14 +247,11 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* dllName;
if (options->driverSpecific && getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &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 = (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),
.pciDeviceId = {
.deviceId = deviceId,
.vendorId = vendorId,
@@ -317,7 +266,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
},
.luid = adapterLuid,
},
(FFGpuDriverResult){
(FFGpuDriverResult) {
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
@@ -329,21 +278,16 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
.name = &gpu->name,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
},
dllName
);
dllName);
FF_DEBUG("Driver-specific detection completed: %s", error ?: "Success");
}
else if (options->driverSpecific)
{
} else if (options->driverSpecific) {
FF_DEBUG("No driver-specific detection function found for vendor: %s", gpu->vendor.chars);
}
if (gpu->type == FF_GPU_TYPE_UNKNOWN && adapterLuid > 0)
{
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)))
{
D3DKMT_OPENADAPTERFROMLUID openAdapterFromLuid = {.AdapterLuid = *(LUID*) &adapterLuid};
if (NT_SUCCESS(D3DKMTOpenAdapterFromLuid(&openAdapterFromLuid))) {
FF_DEBUG("Successfully opened adapter from LUID");
D3DKMT_ADAPTERTYPE adapterType = {};
@@ -353,24 +297,20 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
.pPrivateDriverData = &adapterType,
.PrivateDriverDataSize = sizeof(adapterType),
};
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo)))
{
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) {
FF_DEBUG("Queried adapter type - HybridDiscrete: %d, HybridIntegrated: %d", adapterType.HybridDiscrete, adapterType.HybridIntegrated);
if (adapterType.HybridDiscrete)
if (adapterType.HybridDiscrete) {
gpu->type = FF_GPU_TYPE_DISCRETE;
else if (adapterType.HybridIntegrated)
} else if (adapterType.HybridIntegrated) {
gpu->type = FF_GPU_TYPE_INTEGRATED;
}
else
{
}
} else {
FF_DEBUG("Failed to query adapter type");
}
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET && ffIsWindows11OrGreater())
{
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET && ffIsWindows11OrGreater()) {
FF_DEBUG("Trying to get GPU frequency information");
for (ULONG nodeIdx = 0; ; nodeIdx++)
{
for (ULONG nodeIdx = 0;; nodeIdx++) {
D3DKMT_NODEMETADATA nodeMetadata = {
.NodeOrdinalAndAdapterIndex = (0 << 16) | nodeIdx,
};
@@ -380,78 +320,65 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
.pPrivateDriverData = &nodeMetadata,
.PrivateDriverDataSize = sizeof(nodeMetadata),
};
if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo)))
{
if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) {
FF_DEBUG("No more nodes to query (index %lu)", nodeIdx);
break;
}
if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D)
{
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 },
.AdapterLuid = *(LUID*) &adapterLuid,
.QueryNode2 = {.PhysicalAdapterIndex = 0, .NodeOrdinal = (UINT16) nodeIdx},
};
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)))
{
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
{
} else {
FF_DEBUG("Failed to query node statistics for node %lu", nodeIdx);
}
}
}
D3DKMT_CLOSEADAPTER closeAdapter = { .hAdapter = openAdapterFromLuid.hAdapter };
D3DKMT_CLOSEADAPTER closeAdapter = {.hAdapter = openAdapterFromLuid.hAdapter};
(void) D3DKMTCloseAdapter(&closeAdapter);
openAdapterFromLuid.hAdapter = (D3DKMT_HANDLE) {};
FF_DEBUG("Closed adapter handle");
}
else
{
} else {
FF_DEBUG("Failed to open adapter from LUID");
}
if (options->temp && gpu->temperature == FF_GPU_TEMP_UNSET && ffIsWindows10OrGreater())
{
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 },
.AdapterLuid = *(LUID*) &adapterLuid,
.QueryPhysAdapter = {.PhysicalAdapterIndex = 0},
};
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)) &&
queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature != 0)
{
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
{
} else {
FF_DEBUG("Failed to get GPU temperature or temperature is 0");
}
}
if (options->driverSpecific && gpu->dedicated.used == FF_GPU_VMEM_SIZE_UNSET && ffIsWindows11OrGreater())
{
if (options->driverSpecific && gpu->dedicated.used == FF_GPU_VMEM_SIZE_UNSET && ffIsWindows11OrGreater()) {
FF_DEBUG("Trying to get used video memory from D3DKMT method");
D3DKMT_QUERYSTATISTICS queryStatistics = {
.Type = D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE,
.AdapterLuid = *(LUID*)&adapterLuid,
.AdapterLuid = *(LUID*) &adapterLuid,
.QuerySegmentGroupUsage = {
.PhysicalAdapterIndex = 0,
.SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL,
},
};
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)))
{
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) {
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;
@@ -459,15 +386,12 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->dedicated.total = total;
FF_DEBUG("Found local memory size %llu / %llu", used, total);
}
else
{
} else {
FF_DEBUG("Failed to query segment group usage for local memory");
}
queryStatistics.QuerySegmentGroupUsage.SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL;
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)))
{
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) {
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;
@@ -475,45 +399,38 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->shared.total = total;
FF_DEBUG("Found non-local memory size %llu / %llu", used, total);
}
else
{
} else {
FF_DEBUG("Failed to query segment group usage for non-local memory");
}
}
}
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (gpu->type == FF_GPU_TYPE_UNKNOWN) {
FF_DEBUG("Using fallback GPU type detection");
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
}
} 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;
}
if (gpu->type != FF_GPU_TYPE_UNKNOWN)
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())
{
const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult* gpu);
FF_MAYBE_UNUSED const char* error = ffGPUDetectTypeWithDXCore(*(LUID*)&adapterLuid, gpu);
} else if (ffIsWindows10OrGreater()) {
const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult * gpu);
FF_MAYBE_UNUSED const char* error = ffGPUDetectTypeWithDXCore(*(LUID*) &adapterLuid, gpu);
FF_DEBUG("DXCore GPU type detection result: %s", error ?: "Success");
}
else
} 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);
+25 -30
View File
@@ -1,5 +1,4 @@
extern "C"
{
extern "C" {
#include "gpu.h"
#include "common/library.h"
#include "common/debug.h"
@@ -7,16 +6,16 @@ extern "C"
#if __has_include(<directx/dxcore.h>) && __has_include(<dxguids/dxguids.h>)
#include <directx/dxcore.h>
#include <dxguids/dxguids.h>
#include "common/windows/util.hpp"
# include <directx/dxcore.h>
# include <dxguids/dxguids.h>
# include "common/windows/util.hpp"
static IDXCoreAdapterFactory* loadDxCoreFactory()
{
static IDXCoreAdapterFactory* loadDxCoreFactory() {
static bool initialized = false;
static IDXCoreAdapterFactory* factory = nullptr;
if (initialized)
if (initialized) {
return factory; // Already loaded
}
initialized = true;
FF_LIBRARY_LOAD(dxcore, NULL, "dxcore" FF_LIBRARY_EXTENSION, 1)
@@ -24,16 +23,17 @@ static IDXCoreAdapterFactory* loadDxCoreFactory()
// DXCoreCreateAdapterFactory is a reloaded function, so we can't use FF_LIBRARY_LOAD_SYMBOL_MESSAGE here
typedef HRESULT (*DXCoreCreateAdapterFactory_t)(REFIID riid, void** ppvFactory);
#ifndef FF_DISABLE_DLOPEN
auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) dlsym(dxcore, "DXCoreCreateAdapterFactory");
if (ffDXCoreCreateAdapterFactory == nullptr) return NULL;
#else
auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) DXCoreCreateAdapterFactory;
#endif
# ifndef FF_DISABLE_DLOPEN
auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) dlsym(dxcore, "DXCoreCreateAdapterFactory");
if (ffDXCoreCreateAdapterFactory == nullptr) {
return NULL;
}
# else
auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) DXCoreCreateAdapterFactory;
# endif
HRESULT hr = ffDXCoreCreateAdapterFactory(IID_PPV_ARGS(&factory));
if (FAILED(hr))
{
if (FAILED(hr)) {
FF_DEBUG("DXCoreCreateAdapterFactory failed with HRESULT: 0x%08lX (%s)", hr, ffDebugHResult(hr));
return NULL;
}
@@ -42,27 +42,24 @@ static IDXCoreAdapterFactory* loadDxCoreFactory()
return factory;
}
extern "C"
const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult* gpu)
{
extern "C" const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult* gpu) {
auto* factory = loadDxCoreFactory();
if (!factory)
if (!factory) {
return "Failed to load DXCore library or create adapter factory";
}
IDXCoreAdapter *adapter = nullptr;
IDXCoreAdapter* adapter = nullptr;
HRESULT hr = factory->GetAdapterByLuid(adapterLuid, IID_PPV_ARGS(&adapter));
if (FAILED(hr))
{
if (FAILED(hr)) {
FF_DEBUG("GetAdapterByLuid failed with HRESULT: 0x%08lX (%s)", hr, ffDebugHResult(hr));
return "Failed to get adapter by LUID";
}
on_scope_exit releaseAdapter {[adapter] { adapter->Release(); }};
on_scope_exit releaseAdapter{[adapter] { adapter->Release(); }};
bool isIntegrated = false;
hr = adapter->GetProperty(DXCoreAdapterProperty::IsIntegrated, sizeof(isIntegrated), &isIntegrated);
if (FAILED(hr))
{
if (FAILED(hr)) {
FF_DEBUG("GetProperty(IsIntegrated) failed with HRESULT: 0x%08lX (%s)", hr, ffDebugHResult(hr));
return "Failed to get adapter properties";
}
@@ -75,11 +72,9 @@ const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult* gpu)
#else
#warning "DXCore headers not available, GPU type detection may be less accurate"
# warning "DXCore headers not available, GPU type detection may be less accurate"
extern "C"
const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult* gpu)
{
extern "C" const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult* gpu) {
FF_UNUSED(adapterLuid, gpu);
FF_DEBUG("DXCore not available, skipping GPU type detection with DXCore");
return "DXCore not available";
+124 -163
View File
@@ -1,43 +1,37 @@
#if __x86_64__ || __aarch64__ // WSL2 only supports x86_64 and aarch64
#include "detection/gpu/gpu.h"
#include "detection/gpu/gpu_driver_specific.h"
#include "common/io.h"
#include "common/debug.h"
# include "detection/gpu/gpu.h"
# include "detection/gpu/gpu_driver_specific.h"
# include "common/io.h"
# include "common/debug.h"
#include "d3dkmthk.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <uchar.h>
# include "d3dkmthk.h"
# include <unistd.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <uchar.h>
static void ffStrbufAppendUtf16(FFstrbuf* strbuf, const char16_t* str)
{
static void ffStrbufAppendUtf16(FFstrbuf* strbuf, const char16_t* str) {
mbstate_t state = {};
while (*str)
{
while (*str) {
char buf[5];
size_t len = c16rtomb(buf, *str, &state);
if (len == (size_t) -1)
if (len == (size_t) -1) {
ffStrbufAppendS(strbuf, "�"); // U+FFFD REPLACEMENT CHARACTER
else if (len > 0)
} else if (len > 0) {
ffStrbufAppendNS(strbuf, (uint32_t) len, buf);
}
str++;
}
}
const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus)
{
const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) {
FF_AUTO_CLOSE_FD int dxg = open("/dev/dxg", O_RDWR); // Windows DXCore/D3DKMT adapter driver for WSL
if (dxg < 0)
{
if (errno == ENOENT)
{
if (dxg < 0) {
if (errno == ENOENT) {
FF_DEBUG("/dev/dxg is not available, WSL DXCore GPU driver not detected");
return "No DXCore GPU driver detected (no /dev/dxg)";
}
else
{
} else {
FF_DEBUG("Failed to open /dev/dxg: %s", strerror(errno));
return "Failed to open /dev/dxg";
}
@@ -50,32 +44,28 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus)
.NumAdapters = ARRAY_SIZE(adapters),
.pAdapters = adapters,
};
if (!NT_SUCCESS(D3DKMTEnumAdapters2(dxg, &enumAdapters)))
{
if (!NT_SUCCESS(D3DKMTEnumAdapters2(dxg, &enumAdapters))) {
FF_DEBUG("D3DKMTEnumAdapters2 failed: %s", strerror(errno));
return "Failed to enumerate adapters with D3DKMTEnumAdapters2";
}
FF_DEBUG("D3DKMTEnumAdapters2 succeeded, adapter count: %u", enumAdapters.NumAdapters);
for (uint32_t i = 0; i < enumAdapters.NumAdapters; i++)
{
for (uint32_t i = 0; i < enumAdapters.NumAdapters; i++) {
const D3DKMT_ADAPTERINFO* adapter = &adapters[i];
FF_DEBUG("Processing adapter #%u", i);
D3DKMT_ADAPTERTYPE adapterType;
if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) {
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_ADAPTERTYPE,
.pPrivateDriverData = &adapterType,
.PrivateDriverDataSize = sizeof(adapterType),
})))
{
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_ADAPTERTYPE,
.pPrivateDriverData = &adapterType,
.PrivateDriverDataSize = sizeof(adapterType),
}))) {
FF_DEBUG("KMTQAITYPE_ADAPTERTYPE query failed for adapter #%u: %s", i, strerror(errno));
continue;
}
if (adapterType.SoftwareDevice)
{
if (adapterType.SoftwareDevice) {
FF_DEBUG("Skipping software adapter #%u", i);
continue;
}
@@ -96,100 +86,83 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus)
gpu->type = adapterType.HybridIntegrated
? FF_GPU_TYPE_INTEGRATED
: adapterType.HybridDiscrete
? FF_GPU_TYPE_DISCRETE
: FF_GPU_TYPE_UNKNOWN;
? FF_GPU_TYPE_DISCRETE
: FF_GPU_TYPE_UNKNOWN;
const char* vendorStr = NULL;
D3DKMT_QUERY_DEVICE_IDS deviceIds = { .PhysicalAdapterIndex = 0 };
D3DKMT_QUERY_DEVICE_IDS deviceIds = {.PhysicalAdapterIndex = 0};
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) {
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_PHYSICALADAPTERDEVICEIDS,
.pPrivateDriverData = &deviceIds,
.PrivateDriverDataSize = sizeof(deviceIds),
})))
{
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_PHYSICALADAPTERDEVICEIDS,
.pPrivateDriverData = &deviceIds,
.PrivateDriverDataSize = sizeof(deviceIds),
}))) {
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
} else {
FF_DEBUG("KMTQAITYPE_PHYSICALADAPTERDEVICEIDS query failed for adapter #%u: %s", i, strerror(errno));
}
D3DKMT_ADAPTERADDRESS adapterAddress;
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) {
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_ADAPTERADDRESS,
.pPrivateDriverData = &adapterAddress,
.PrivateDriverDataSize = sizeof(adapterAddress),
})))
{
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_ADAPTERADDRESS,
.pPrivateDriverData = &adapterAddress,
.PrivateDriverDataSize = sizeof(adapterAddress),
}))) {
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
{
} else {
adapterAddress.BusNumber = -1u;
gpu->deviceId = ffGPUGeneral2Id(((uint64_t)adapter->AdapterLuid.HighPart << 32) | (uint64_t)adapter->AdapterLuid.LowPart);
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, strerror(errno));
}
D3DKMT_UMD_DRIVER_VERSION umdDriverVersion;
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) {
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_UMD_DRIVER_VERSION,
.pPrivateDriverData = &umdDriverVersion,
.PrivateDriverDataSize = sizeof(umdDriverVersion),
})))
{
ffStrbufSetF(&gpu->driver, "%lu.%lu.%lu.%lu",
umdDriverVersion.DriverVersion.QuadPart >> 48ul & 0xFFFF,
umdDriverVersion.DriverVersion.QuadPart >> 32ul & 0xFFFF,
umdDriverVersion.DriverVersion.QuadPart >> 16ul & 0xFFFF,
umdDriverVersion.DriverVersion.QuadPart >> 0ul & 0xFFFF);
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_UMD_DRIVER_VERSION,
.pPrivateDriverData = &umdDriverVersion,
.PrivateDriverDataSize = sizeof(umdDriverVersion),
}))) {
ffStrbufSetF(&gpu->driver, "%lu.%lu.%lu.%lu", umdDriverVersion.DriverVersion.QuadPart >> 48ul & 0xFFFF, umdDriverVersion.DriverVersion.QuadPart >> 32ul & 0xFFFF, umdDriverVersion.DriverVersion.QuadPart >> 16ul & 0xFFFF, umdDriverVersion.DriverVersion.QuadPart >> 0ul & 0xFFFF);
FF_DEBUG("Adapter #%u UMD driver version: %08lX", i, (unsigned long) umdDriverVersion.DriverVersion.QuadPart);
}
else
{
} else {
FF_DEBUG("KMTQAITYPE_UMD_DRIVER_VERSION query failed for adapter #%u: %s", i, strerror(errno));
}
D3DKMT_DRIVERVERSION wddmVersion = KMT_DRIVERVERSION_WDDM_3_0;
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) {
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_DRIVERVERSION,
.pPrivateDriverData = &wddmVersion,
.PrivateDriverDataSize = sizeof(wddmVersion),
})))
{
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_DRIVERVERSION,
.pPrivateDriverData = &wddmVersion,
.PrivateDriverDataSize = sizeof(wddmVersion),
}))) {
ffStrbufSetF(&gpu->platformApi, "WDDM %u.%u", wddmVersion / 1000, (wddmVersion % 1000) / 100);
FF_DEBUG("Adapter #%u WDDM version: %u", i, wddmVersion);
}
else
{
} else {
ffStrbufSetStatic(&gpu->platformApi, "WDDM");
FF_DEBUG("KMTQAITYPE_DRIVERVERSION query failed for adapter #%u", i);
}
if (gpu->name.length == 0)
{
if (gpu->name.length == 0) {
D3DKMT_ADAPTERREGISTRYINFO registryInfo;
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) {
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_ADAPTERREGISTRYINFO,
.pPrivateDriverData = &registryInfo,
.PrivateDriverDataSize = sizeof(registryInfo),
})))
{
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_ADAPTERREGISTRYINFO,
.pPrivateDriverData = &registryInfo,
.PrivateDriverDataSize = sizeof(registryInfo),
}))) {
ffStrbufAppendUtf16(&gpu->name, registryInfo.AdapterString);
FF_DEBUG("Adapter #%u adapter string: %s", i, gpu->name.chars);
}
else
} else {
FF_DEBUG("KMTQAITYPE_ADAPTERREGISTRYINFO query failed for adapter #%u: %s", i, strerror(errno));
}
}
if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->driverSpecific)
{
if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->driverSpecific) {
FF_DEBUG("Trying NVIDIA driver-specific detection for adapter #%u", i);
FFGpuDriverCondition cond = {
.type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | (adapterAddress.DeviceNumber != -1u ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0),
@@ -206,26 +179,26 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus)
.func = adapterAddress.FunctionNumber,
},
};
const char* error = ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult){
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = &gpu->name,
}, "/usr/lib/wsl/lib/libnvidia-ml.so");
if (error)
const char* error = ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult) {
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = &gpu->name,
},
"/usr/lib/wsl/lib/libnvidia-ml.so");
if (error) {
FF_DEBUG("NVIDIA driver-specific detection failed for adapter #%u: %s", i, error);
else
} else {
FF_DEBUG("NVIDIA driver-specific detection succeeded for adapter #%u", i);
}
}
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)
{
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,
@@ -235,33 +208,29 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus)
.SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL,
},
};
if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics)))
{
if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics))) {
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("Adapter #%u local memory usage: used=%lu total=%lu", i, (unsigned long) used, (unsigned long) total);
}
else
} else {
FF_DEBUG("D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE (LOCAL) failed for adapter #%u: %s", i, strerror(errno));
}
queryStatistics.QuerySegmentGroupUsage.SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL;
if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics)))
{
if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics))) {
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("Adapter #%u non-local memory usage: used=%lu total=%lu", i, (unsigned long) used, (unsigned long) total);
}
else
} else {
FF_DEBUG("D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE (NON_LOCAL) failed for adapter #%u: %s", i, strerror(errno));
}
else
{
}
} else {
// Supports basic segment (total) size query
D3DKMT_SEGMENTSIZEINFO segmentSizeInfo = {};
D3DKMT_QUERYADAPTERINFO queryAdapterInfo = {
@@ -270,87 +239,80 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus)
.pPrivateDriverData = &segmentSizeInfo,
.PrivateDriverDataSize = sizeof(segmentSizeInfo),
};
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &queryAdapterInfo)))
{
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &queryAdapterInfo))) {
FF_DEBUG("Adapter #%u segment size - DedicatedVideoMemorySize: %lu, DedicatedSystemMemorySize: %lu, SharedSystemMemorySize: %lu",
i, segmentSizeInfo.DedicatedVideoMemorySize, segmentSizeInfo.DedicatedSystemMemorySize, segmentSizeInfo.SharedSystemMemorySize);
i,
segmentSizeInfo.DedicatedVideoMemorySize,
segmentSizeInfo.DedicatedSystemMemorySize,
segmentSizeInfo.SharedSystemMemorySize);
gpu->dedicated.total = segmentSizeInfo.DedicatedVideoMemorySize;
gpu->shared.total = segmentSizeInfo.DedicatedSystemMemorySize + segmentSizeInfo.SharedSystemMemorySize;
}
else
{
} else {
FF_DEBUG("Failed to query segment size information for adapter #%u: %s", i, strerror(errno));
}
}
}
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET && wddmVersion >= KMT_DRIVERVERSION_WDDM_3_1)
{
for (ULONG nodeIdx = 0; ; nodeIdx++)
{
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET && wddmVersion >= KMT_DRIVERVERSION_WDDM_3_1) {
for (ULONG nodeIdx = 0;; nodeIdx++) {
D3DKMT_NODEMETADATA nodeMetadata = {
.NodeOrdinalAndAdapterIndex = (0 << 16) | nodeIdx,
};
if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) {
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_NODEMETADATA,
.pPrivateDriverData = &nodeMetadata,
.PrivateDriverDataSize = sizeof(nodeMetadata),
})))
.hAdapter = adapter->hAdapter,
.Type = KMTQAITYPE_NODEMETADATA,
.pPrivateDriverData = &nodeMetadata,
.PrivateDriverDataSize = sizeof(nodeMetadata),
}))) {
break;
}
if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D)
if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D) {
continue;
}
D3DKMT_QUERYSTATISTICS queryStatistics = {
.Type = D3DKMT_QUERYSTATISTICS_NODE2,
.AdapterLuid = adapter->AdapterLuid,
.QueryNode2 = { .PhysicalAdapterIndex = 0, .NodeOrdinal = (UINT16) nodeIdx },
.QueryNode2 = {.PhysicalAdapterIndex = 0, .NodeOrdinal = (UINT16) nodeIdx},
};
if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics)))
{
if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics))) {
gpu->frequency = (uint32_t) (queryStatistics.QueryResult.NodeInformation.NodePerfData.MaxFrequency / 1000 / 1000);
FF_DEBUG("Adapter #%u max graphics frequency: %u MHz", i, gpu->frequency);
break;
}
else
} else {
FF_DEBUG("Failed to query node performance data for adapter #%u node #%u: %s", i, nodeIdx, strerror(errno));
}
}
}
if (options->temp && gpu->temperature == FF_GPU_TEMP_UNSET)
{
if (options->temp && gpu->temperature == FF_GPU_TEMP_UNSET) {
D3DKMT_QUERYSTATISTICS queryStatistics = {
.Type = D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER,
.AdapterLuid = adapter->AdapterLuid,
.QueryPhysAdapter = { .PhysicalAdapterIndex = 0 },
.QueryPhysAdapter = {.PhysicalAdapterIndex = 0},
};
if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics)) &&
queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature != 0)
{
queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature != 0) {
gpu->temperature = queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature / 10.0;
FF_DEBUG("Adapter #%u temperature: %.1f°C", i, gpu->temperature);
}
else
} else {
FF_DEBUG("Failed to query temperature for adapter #%u: %s", i, strerror(errno));
}
}
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
if (gpu->type == FF_GPU_TYPE_UNKNOWN) {
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
}
} else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) {
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) {
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
}
} 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;
}
@@ -363,12 +325,11 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus)
(unsigned) gpu->type,
(unsigned long) gpu->deviceId);
if (NT_SUCCESS(D3DKMTCloseAdapter(dxg, &(D3DKMT_CLOSEADAPTER) {
.hAdapter = adapter->hAdapter
})))
if (NT_SUCCESS(D3DKMTCloseAdapter(dxg, &(D3DKMT_CLOSEADAPTER) {.hAdapter = adapter->hAdapter}))) {
FF_DEBUG("Closed adapter #%u successfully", i);
else
} else {
FF_DEBUG("Failed to close adapter #%u: %s", i, strerror(errno));
}
}
return NULL;
+23 -40
View File
@@ -7,25 +7,22 @@
#include <stdint.h>
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv412ctl_result_t
typedef enum ctl_result_t
{
typedef enum ctl_result_t {
CTL_RESULT_SUCCESS = 0,
} ctl_result_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv420ctl_application_id_t
typedef struct ctl_application_id_t
{
typedef struct ctl_application_id_t {
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
} ctl_application_id_t;
#define CTL_IMPL_VERSION (( 1 /*major*/ << 16 )|( 1 /*minor*/ & 0x0000ffff))
#define CTL_IMPL_VERSION ((1 /*major*/ << 16) | (1 /*minor*/ & 0x0000ffff))
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv415ctl_init_flag_t
typedef enum ctl_init_flag_t
{
typedef enum ctl_init_flag_t {
CTL_INIT_FLAG_USE_LEVEL_ZERO = 1,
CTL_INIT_FLAG_MAX
} ctl_init_flag_t;
@@ -33,8 +30,7 @@ typedef enum ctl_init_flag_t
typedef uint32_t ctl_version_info_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv415ctl_init_args_t
typedef struct ctl_init_args_t
{
typedef struct ctl_init_args_t {
uint32_t Size;
uint8_t Version;
ctl_version_info_t AppVersion;
@@ -46,34 +42,31 @@ typedef struct ctl_init_args_t
typedef struct ctl_api_handle_t* ctl_api_handle_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv47ctlInitP15ctl_init_args_tP16ctl_api_handle_t
extern ctl_result_t ctlInit(ctl_init_args_t *pInitDesc, ctl_api_handle_t *phAPIHandle);
extern ctl_result_t ctlInit(ctl_init_args_t* pInitDesc, ctl_api_handle_t* phAPIHandle);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctlclose
extern ctl_result_t ctlClose(ctl_api_handle_t hAPIHandle);
typedef struct ctl_device_adapter_handle_t* ctl_device_adapter_handle_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv419ctlEnumerateDevices16ctl_api_handle_tP8uint32_tP27ctl_device_adapter_handle_t
extern ctl_result_t ctlEnumerateDevices(ctl_api_handle_t hAPIHandle, uint32_t *pCount, ctl_device_adapter_handle_t* phDevices);
extern ctl_result_t ctlEnumerateDevices(ctl_api_handle_t hAPIHandle, uint32_t* pCount, ctl_device_adapter_handle_t* phDevices);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv417ctl_device_type_t
typedef enum ctl_device_type_t
{
typedef enum ctl_device_type_t {
CTL_DEVICE_TYPE_GRAPHICS = 1,
CTL_DEVICE_TYPE_SYSTEM = 2,
CTL_DEVICE_TYPE_MAX
} ctl_device_type_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv422ctl_firmware_version_t
typedef struct ctl_firmware_version_t
{
typedef struct ctl_firmware_version_t {
uint64_t major_version;
uint64_t minor_version;
uint64_t build_number;
} ctl_firmware_version_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv417ctl_adapter_bdf_t
typedef struct ctl_adapter_bdf_t
{
typedef struct ctl_adapter_bdf_t {
uint8_t bus;
uint8_t device;
uint8_t function;
@@ -82,14 +75,12 @@ typedef struct ctl_adapter_bdf_t
#define IGCL_CTL_MAX_DEVICE_NAME_LEN 100
#define IGCL_CTL_MAX_RESERVED_SIZE 112
typedef enum ctl_adapter_properties_flag_t
{
typedef enum ctl_adapter_properties_flag_t {
CTL_ADAPTER_PROPERTIES_FLAG_INTEGRATED = 1,
} ctl_adapter_properties_flag_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv431ctl_device_adapter_properties_t
typedef struct ctl_device_adapter_properties_t
{
typedef struct ctl_device_adapter_properties_t {
uint32_t Size;
uint8_t Version;
void* pDeviceID;
@@ -122,8 +113,7 @@ typedef struct ctl_temp_handle_t* ctl_temp_handle_t;
extern ctl_result_t ctlEnumTemperatureSensors(ctl_device_adapter_handle_t hDAhandle, uint32_t* pCount, ctl_temp_handle_t* phTemperature);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv427ctlTemperatureGetProperties17ctl_temp_handle_tP21ctl_temp_properties_t
typedef enum ctl_temp_sensors_t
{
typedef enum ctl_temp_sensors_t {
CTL_TEMP_SENSORS_GLOBAL = 0,
CTL_TEMP_SENSORS_GPU = 1,
CTL_TEMP_SENSORS_MEMORY = 2,
@@ -133,8 +123,7 @@ typedef enum ctl_temp_sensors_t
CTL_TEMP_SENSORS_MAX
} ctl_temp_sensors_t;
typedef struct _ctl_temp_properties_t
{
typedef struct _ctl_temp_properties_t {
uint32_t Size;
uint8_t Version;
ctl_temp_sensors_t type;
@@ -147,11 +136,10 @@ extern ctl_result_t ctlTemperatureGetProperties(ctl_temp_handle_t hTemperature,
typedef struct ctl_mem_handle_t* ctl_mem_handle_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv420ctlEnumMemoryModules27ctl_device_adapter_handle_tP8uint32_tP16ctl_mem_handle_t
extern ctl_result_t ctlEnumMemoryModules(ctl_device_adapter_handle_t hDAhandle, uint32_t *pCount, ctl_mem_handle_t* phMemory);
extern ctl_result_t ctlEnumMemoryModules(ctl_device_adapter_handle_t hDAhandle, uint32_t* pCount, ctl_mem_handle_t* phMemory);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv415ctl_mem_state_t
typedef struct ctl_mem_state_t
{
typedef struct ctl_mem_state_t {
uint32_t Size;
uint8_t Version;
uint64_t free;
@@ -159,11 +147,10 @@ typedef struct ctl_mem_state_t
} ctl_mem_state_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv417ctlMemoryGetState16ctl_mem_handle_tP15ctl_mem_state_t
extern ctl_result_t ctlMemoryGetState(ctl_mem_handle_t hMemory, ctl_mem_state_t *pState);
extern ctl_result_t ctlMemoryGetState(ctl_mem_handle_t hMemory, ctl_mem_state_t* pState);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv414ctl_mem_type_t
typedef enum ctl_mem_type_t
{
typedef enum ctl_mem_type_t {
CTL_MEM_TYPE_HBM = 0,
CTL_MEM_TYPE_DDR = 1,
CTL_MEM_TYPE_DDR3 = 2,
@@ -183,16 +170,14 @@ typedef enum ctl_mem_type_t
} ctl_mem_type_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv413ctl_mem_loc_t
typedef enum ctl_mem_loc_t
{
typedef enum ctl_mem_loc_t {
CTL_MEM_LOC_SYSTEM = 0,
CTL_MEM_LOC_DEVICE = 1,
CTL_MEM_LOC_MAX
} ctl_mem_loc_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv420ctl_mem_properties_t
typedef struct ctl_mem_properties_t
{
typedef struct ctl_mem_properties_t {
uint32_t Size;
uint8_t Version;
ctl_mem_type_t type;
@@ -203,7 +188,7 @@ typedef struct ctl_mem_properties_t
} ctl_mem_properties_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv422ctlMemoryGetProperties16ctl_mem_handle_tP20ctl_mem_properties_t
extern ctl_result_t ctlMemoryGetProperties(ctl_mem_handle_t hMemory, ctl_mem_properties_t *pProperties);
extern ctl_result_t ctlMemoryGetProperties(ctl_mem_handle_t hMemory, ctl_mem_properties_t* pProperties);
typedef struct ctl_freq_handle_t* ctl_freq_handle_t;
@@ -211,16 +196,14 @@ typedef struct ctl_freq_handle_t* ctl_freq_handle_t;
extern ctl_result_t ctlEnumFrequencyDomains(ctl_device_adapter_handle_t hDAhandle, uint32_t* pCount, ctl_freq_handle_t* phFrequency);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv417ctl_freq_domain_t
typedef enum ctl_freq_domain_t
{
typedef enum ctl_freq_domain_t {
CTL_FREQ_DOMAIN_GPU = 0,
CTL_FREQ_DOMAIN_MEMORY = 1,
CTL_FREQ_DOMAIN_MAX
} ctl_freq_domain_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv421ctl_freq_properties_t
typedef struct ctl_freq_properties_t
{
typedef struct ctl_freq_properties_t {
uint32_t Size;
uint8_t Version;
ctl_freq_domain_t type;
+63 -63
View File
@@ -9,52 +9,52 @@
* Copyright © 2023 Intel Corporation
*/
#define DRM_XE_DEVICE_QUERY 0x00
#define DRM_XE_DEVICE_QUERY 0x00
#define DRM_IOCTL_XE_DEVICE_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query)
#define DRM_IOCTL_XE_DEVICE_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query)
enum drm_xe_memory_class {
DRM_XE_MEM_REGION_CLASS_SYSMEM = 0,
DRM_XE_MEM_REGION_CLASS_VRAM
DRM_XE_MEM_REGION_CLASS_SYSMEM = 0,
DRM_XE_MEM_REGION_CLASS_VRAM
};
struct drm_xe_mem_region {
__u16 mem_class;
__u16 instance;
__u32 min_page_size;
__u64 total_size;
__u64 used;
__u64 cpu_visible_size;
__u64 cpu_visible_used;
__u64 reserved[6];
__u16 mem_class;
__u16 instance;
__u32 min_page_size;
__u64 total_size;
__u64 used;
__u64 cpu_visible_size;
__u64 cpu_visible_used;
__u64 reserved[6];
};
struct drm_xe_query_mem_regions {
__u32 num_mem_regions;
__u32 pad;
struct drm_xe_mem_region mem_regions[];
__u32 num_mem_regions;
__u32 pad;
struct drm_xe_mem_region mem_regions[];
};
struct drm_xe_query_topology_mask {
__u16 gt_id;
__u16 gt_id;
#define DRM_XE_TOPO_DSS_GEOMETRY 1
#define DRM_XE_TOPO_DSS_COMPUTE 2
#define DRM_XE_TOPO_EU_PER_DSS 4
__u16 type;
__u32 num_bytes;
__u8 mask[];
#define DRM_XE_TOPO_DSS_GEOMETRY 1
#define DRM_XE_TOPO_DSS_COMPUTE 2
#define DRM_XE_TOPO_EU_PER_DSS 4
__u16 type;
__u32 num_bytes;
__u8 mask[];
};
struct drm_xe_device_query {
__u64 extensions;
__u64 extensions;
#define DRM_XE_DEVICE_QUERY_MEM_REGIONS 1
#define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 5
__u32 query;
__u32 size;
__u64 data;
__u64 reserved[2];
#define DRM_XE_DEVICE_QUERY_MEM_REGIONS 1
#define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 5
__u32 query;
__u32 size;
__u64 data;
__u64 reserved[2];
};
// i915_drm.h
@@ -64,62 +64,62 @@ struct drm_xe_device_query {
* All Rights Reserved.
*/
#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
struct drm_i915_getparam {
__s32 param;
int *value;
__s32 param;
int* value;
};
typedef struct drm_i915_getparam drm_i915_getparam_t;
#define DRM_I915_GETPARAM 0x06
#define DRM_I915_QUERY 0x39
#define DRM_I915_QUERY_MEMORY_REGIONS 4
#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
#define I915_PARAM_EU_TOTAL 34
#define DRM_I915_GETPARAM 0x06
#define DRM_I915_QUERY 0x39
#define DRM_I915_QUERY_MEMORY_REGIONS 4
#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
#define I915_PARAM_EU_TOTAL 34
struct drm_i915_query_item {
__u64 query_id;
#define DRM_I915_QUERY_MEMORY_REGIONS 4
__u64 query_id;
#define DRM_I915_QUERY_MEMORY_REGIONS 4
__s32 length;
__u32 flags;
__u64 data_ptr;
__s32 length;
__u32 flags;
__u64 data_ptr;
};
struct drm_i915_query {
__u32 num_items;
__u32 flags;
__u64 items_ptr;
__u32 num_items;
__u32 flags;
__u64 items_ptr;
};
enum drm_i915_gem_memory_class {
I915_MEMORY_CLASS_SYSTEM = 0,
I915_MEMORY_CLASS_DEVICE,
I915_MEMORY_CLASS_SYSTEM = 0,
I915_MEMORY_CLASS_DEVICE,
};
struct drm_i915_gem_memory_class_instance {
__u16 memory_class;
__u16 memory_instance;
__u16 memory_class;
__u16 memory_instance;
};
struct drm_i915_memory_region_info {
struct drm_i915_gem_memory_class_instance region;
__u32 rsvd0;
__u64 probed_size;
__u64 unallocated_size;
struct drm_i915_gem_memory_class_instance region;
__u32 rsvd0;
__u64 probed_size;
__u64 unallocated_size;
union {
__u64 rsvd1[8];
struct {
__u64 probed_cpu_visible_size;
__u64 unallocated_cpu_visible_size;
};
};
union {
__u64 rsvd1[8];
struct {
__u64 probed_cpu_visible_size;
__u64 unallocated_cpu_visible_size;
};
};
};
struct drm_i915_query_memory_regions {
__u32 num_regions;
__u32 rsvd[3];
struct drm_i915_memory_region_info regions[];
__u32 num_regions;
__u32 rsvd[3];
struct drm_i915_memory_region_info regions[];
};
+21 -23
View File
@@ -10,16 +10,14 @@
/**
* Return values for MTML API calls.
*/
typedef enum
{
typedef enum {
MTML_SUCCESS = 0,
} MtmlReturn;
/**
* The brand of the device.
*/
typedef enum
{
typedef enum {
MTML_BRAND_MTT = 0, //!< MTT series.
} MtmlBrandType;
@@ -53,60 +51,60 @@ typedef struct
// Retrieves the number of cores of a device.
MtmlReturn mtmlDeviceCountGpuCores(const MtmlDevice* device, unsigned int* numCores);
// Retrieves the brand of a device.
MtmlReturn mtmlDeviceGetBrand(const MtmlDevice *dev, MtmlBrandType *type);
MtmlReturn mtmlDeviceGetBrand(const MtmlDevice* dev, MtmlBrandType* type);
// Retrieves the index associated with the specified device.
MtmlReturn mtmlDeviceGetIndex(const MtmlDevice *dev, unsigned int *index);
MtmlReturn mtmlDeviceGetIndex(const MtmlDevice* dev, unsigned int* index);
// Retrieves the name of a device.
MtmlReturn mtmlDeviceGetName(const MtmlDevice *dev, char *name, unsigned int length);
MtmlReturn mtmlDeviceGetName(const MtmlDevice* dev, char* name, unsigned int length);
// Retrieves the PCI attributes of a device.
MtmlReturn mtmlDeviceGetPciInfo(const MtmlDevice *dev, MtmlPciInfo *pci);
MtmlReturn mtmlDeviceGetPciInfo(const MtmlDevice* dev, MtmlPciInfo* pci);
/**
* Retrieves the UUID of a specified device. The UUID is a hexadecimal string in the
* form of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where each 'x' is an ASCII character that represents a hexadecimal
* digit. The UUID is globally unique for every single device thus can be used to identify different devices
* physically.
*/
MtmlReturn mtmlDeviceGetUUID(const MtmlDevice *dev, char *uuid, unsigned int length);
MtmlReturn mtmlDeviceGetUUID(const MtmlDevice* dev, char* uuid, unsigned int length);
// Initializes a GPU opaque object to represent a specific graphic core on the target device that is designated by its index.
MtmlReturn mtmlDeviceInitGpu(const MtmlDevice *dev, MtmlGpu **gpu);
MtmlReturn mtmlDeviceInitGpu(const MtmlDevice* dev, MtmlGpu** gpu);
// Initializes a memory opaque object to represent the memory on the target device.
MtmlReturn mtmlDeviceInitMemory(const MtmlDevice *dev, MtmlMemory **mem);
MtmlReturn mtmlDeviceInitMemory(const MtmlDevice* dev, MtmlMemory** mem);
// Retrieves the maximum supported clock speed for the device's graphic core.
MtmlReturn mtmlGpuGetMaxClock(const MtmlGpu *gpu, unsigned int *clockMhz);
MtmlReturn mtmlGpuGetMaxClock(const MtmlGpu* gpu, unsigned int* clockMhz);
// Retrieves the current temperature readings for the device's graphic core, in degrees Celsius.
MtmlReturn mtmlGpuGetTemperature(const MtmlGpu *gpu, unsigned int *temp);
MtmlReturn mtmlGpuGetTemperature(const MtmlGpu* gpu, unsigned int* temp);
// Retrieves the current utilization rate for the device's graphic core.
MtmlReturn mtmlGpuGetUtilization(const MtmlGpu *gpu, unsigned int *utilization);
MtmlReturn mtmlGpuGetUtilization(const MtmlGpu* gpu, unsigned int* utilization);
// Retrieves the number of devices that can be accessed by the library opaque object.
MtmlReturn mtmlLibraryCountDevice(const MtmlLibrary *lib, unsigned int *count);
MtmlReturn mtmlLibraryCountDevice(const MtmlLibrary* lib, unsigned int* count);
/**
* Initializes a device opaque object to represent a device that is designated by its index.
* The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice().
*/
MtmlReturn mtmlLibraryInit(MtmlLibrary **lib);
MtmlReturn mtmlLibraryInit(MtmlLibrary** lib);
/**
* Initializes a device opaque object to represent a device that is designated by its index.
* The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice().
*/
MtmlReturn mtmlLibraryInitDeviceByIndex(const MtmlLibrary *lib, unsigned int index, MtmlDevice **dev);
MtmlReturn mtmlLibraryInitDeviceByIndex(const MtmlLibrary* lib, unsigned int index, MtmlDevice** dev);
/**
* Initializes a device opaque object to represent a device that is designated by its PCI Sbdf.
* The PCI Sbdf format like 00000000:3a:00.0 refer to \ref MtmlPciInfo::sbdf.
*/
MtmlReturn mtmlLibraryInitDeviceByPciSbdf(const MtmlLibrary *lib, const char *pciSbdf, MtmlDevice **dev);
MtmlReturn mtmlLibraryInitDeviceByPciSbdf(const MtmlLibrary* lib, const char* pciSbdf, MtmlDevice** dev);
// Initializes a MtmlSystem opaque pointer that is bound to a library opaque object.
MtmlReturn mtmlLibraryInitSystem(const MtmlLibrary *lib, MtmlSystem **sys);
MtmlReturn mtmlLibraryInitSystem(const MtmlLibrary* lib, MtmlSystem** sys);
/**
* Shuts down the library opaque object that is previously initialized by \ref mtmlLibraryInit() and releases its resources.
* The \a lib pointer cannot be used anymore after this function returns.
*/
MtmlReturn mtmlLibraryShutDown(MtmlLibrary *lib);
MtmlReturn mtmlLibraryShutDown(MtmlLibrary* lib);
// Retrieves the amount of total memory available on the device, in bytes.
MtmlReturn mtmlMemoryGetTotal(const MtmlMemory *mem, unsigned long long *total);
MtmlReturn mtmlMemoryGetTotal(const MtmlMemory* mem, unsigned long long* total);
// Retrieves the amount of used memory on the device, in bytes.
MtmlReturn mtmlMemoryGetUsed(const MtmlMemory *mem, unsigned long long *used);
MtmlReturn mtmlMemoryGetUsed(const MtmlMemory* mem, unsigned long long* used);
// Retrieves the current memory utilization rate for the device.
MtmlReturn mtmlMemoryGetUtilization(const MtmlMemory *mem, unsigned int *utilization);
MtmlReturn mtmlMemoryGetUtilization(const MtmlMemory* mem, unsigned int* utilization);
+6 -9
View File
@@ -2,8 +2,7 @@
// https://github.com/NVIDIA/nvapi (MIT License)
// https://github.com/deathcamp/NVOC/blob/master/nvoc.c (Public Domain)
typedef enum NvApiGPUMemoryType
{
typedef enum NvApiGPUMemoryType {
NVAPI_GPU_MEMORY_TYPE_UNKNOWN = 0,
NVAPI_GPU_MEMORY_TYPE_SDRAM,
NVAPI_GPU_MEMORY_TYPE_DDR1,
@@ -23,18 +22,16 @@ typedef enum NvApiGPUMemoryType
NVAPI_GPU_MEMORY_TYPE_GDDR7,
} NvApiGPUMemoryType;
typedef enum
{
NV_SYSTEM_TYPE_GPU_UNKNOWN = 0,
NV_SYSTEM_TYPE_IGPU = 1, // Integrated
NV_SYSTEM_TYPE_DGPU = 2, // Discrete
typedef enum {
NV_SYSTEM_TYPE_GPU_UNKNOWN = 0,
NV_SYSTEM_TYPE_IGPU = 1, // Integrated
NV_SYSTEM_TYPE_DGPU = 2, // Discrete
} NvApiGPUType;
typedef int NvAPI_Status; // 0 = success; < 0 = error
typedef struct NvPhysicalGpuHandle* NvPhysicalGpuHandle;
typedef enum
{
typedef enum {
NVAPI_INTERFACE_OFFSET_INITIALIZE = 0x0150E828,
NVAPI_INTERFACE_OFFSET_UNLOAD = 0xD22BDD7E,
NVAPI_INTERFACE_OFFSET_ENUM_PHYSICAL_GPUS = 0xE5AC921F,
+5 -5
View File
@@ -54,7 +54,7 @@ typedef struct {
unsigned long long used;
} nvmlMemory_v2_t;
// https://github.com/NVIDIA/nvidia-settings/issues/78#issuecomment-1012837988
enum { nvmlMemory_v2 = (unsigned int)(sizeof(nvmlMemory_v2_t) | (2 << 24U)) };
enum { nvmlMemory_v2 = (unsigned int) (sizeof(nvmlMemory_v2_t) | (2 << 24U)) };
// https://docs.nvidia.com/deploy/nvml-api/structnvmlMemory__t.html#structnvmlMemory__t
// Memory allocation information for a device (v1)
@@ -137,7 +137,7 @@ extern nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, nvmlTemperatur
// Retrieves the amount of used, free, reserved and total memory available on the device, in bytes. The reserved amount is supported on version 2 only
extern nvmlReturn_t nvmlDeviceGetMemoryInfo_v2(nvmlDevice_t device, nvmlMemory_v2_t* memory);
// Retrieves the amount of used, free, total memory available on the device, in bytes.
extern nvmlReturn_t nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t *memory);
extern nvmlReturn_t nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t* memory);
// Gets the device's core count
extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* numCores);
// Retrieves the maximum clock speeds for the device
@@ -145,8 +145,8 @@ extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType
// Retrieves the brand of this device
extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type);
// Retrieves the current utilization rates for the device
extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t *utilization);
extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t* utilization);
// Retrieves the globally unique immutable UUID associated with this device, as a 5 part hexadecimal string, that augments the immutable, board serial identifier.
extern nvmlReturn_t nvmlDeviceGetIndex(nvmlDevice_t device, unsigned int *index);
extern nvmlReturn_t nvmlDeviceGetIndex(nvmlDevice_t device, unsigned int* index);
// Retrieves the name of this device.
extern nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char *name, unsigned int length);
extern nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char* name, unsigned int length);