mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-30 09:33:39 +01:00
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:
@@ -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);
|
||||
|
||||
+683
-683
File diff suppressed because it is too large
Load Diff
+191
-230
@@ -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
@@ -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
@@ -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
@@ -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, ¤tSetting);
|
||||
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";
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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) ¶msGlobal,
|
||||
.size = sizeof(paramsGlobal),
|
||||
}) >= 0)
|
||||
{
|
||||
.param_group = DRM_ASAHI_GET_PARAMS,
|
||||
.pointer = (uintptr_t) ¶msGlobal,
|
||||
.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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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 = ®istryInfo,
|
||||
.PrivateDriverDataSize = sizeof(registryInfo),
|
||||
})))
|
||||
{
|
||||
.hAdapter = adapter->hAdapter,
|
||||
.Type = KMTQAITYPE_ADAPTERREGISTRYINFO,
|
||||
.pPrivateDriverData = ®istryInfo,
|
||||
.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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user