Skip to content

Commit 8dafd8f

Browse files
committed
GPU (Windows): rewrite implementation for AMD GPUs using ADL SDK
Detect more information including memory type
1 parent c9a1765 commit 8dafd8f

File tree

6 files changed

+167
-435
lines changed

6 files changed

+167
-435
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,9 +659,6 @@ jobs:
659659
- name: copy necessary dlls
660660
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
661661

662-
- name: download amd_ags
663-
run: curl -LO https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/raw/master/ags_lib/lib/amd_ags_x64.dll
664-
665662
- name: list features
666663
run: ./fastfetch --list-features
667664

src/3rdparty/ags/amd_ags.h

Lines changed: 0 additions & 383 deletions
This file was deleted.

src/3rdparty/ags/repo.json

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/detection/gpu/adl.h

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,44 @@
44

55
// https://gpuopen-librariesandsdks.github.io/adl/modules.html
66

7-
// ADLOD6CurrentStatus ADL2_Overdrive6_Temperature_Get
8-
// https://gpuopen-librariesandsdks.github.io/adl/group__OVERDRIVE6API.html#ga10021644bfab0e3910e10caaa7c0053c
7+
// Function to initialize the ADL2 interface and to obtain client's context handle.
8+
extern int ADL2_Main_Control_Create(ADL_MAIN_MALLOC_CALLBACK callback, int iEnumConnectedAdapters, ADL_CONTEXT_HANDLE* context);
99

10-
// ADL2_Adapter_DedicatedVRAMUsage_Get ADL2_Adapter_VRAMUsage_Get
11-
// https://gpuopen-librariesandsdks.github.io/adl/group__ADAPTERMAINAPI.html#ga9c41c3740ddd76ee4f8a33a3ccc55e7f
10+
// Destroy client's ADL context.
11+
extern int ADL2_Main_Control_Destroy(ADL_CONTEXT_HANDLE context);
1212

13-
// ADL_ASIC_DISCRETE ADL_Adapter_ASICFamilyType_Get
14-
// https://gpuopen-librariesandsdks.github.io/adl/group__ADAPTERMAINAPI.html#ga345082fdc7c14fc5179605732085d272
13+
// Retrieves adapter information for given adapter or all OS-known adapters.
14+
// Return 1 on success
15+
extern int ADL2_Adapter_AdapterInfoX3_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* numAdapters, AdapterInfo** lppAdapterInfo);
16+
17+
// Function to retrieve Graphic Core Info.
18+
// Return ADL_OK on success
19+
extern int ADL2_Adapter_Graphic_Core_Info_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLGraphicCoreInfo* pGraphicCoreInfo);
20+
21+
// Function to retrieve memory information from the adapter. Version 2
22+
// Return ADL_OK on success
23+
extern int ADL2_Adapter_MemoryInfo2_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLMemoryInfo2* lpMemoryInfo2);
24+
25+
// This function retrieves the VRAM usage of given adapter.
26+
// Return ADL_OK on success
27+
extern int ADL2_Adapter_VRAMUsage_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iVRAMUsageInMB);
28+
29+
// This function retrieves the Dedicated VRAM usage of given adapter.
30+
// Return ADL_OK on success
31+
extern int ADL2_Adapter_DedicatedVRAMUsage_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iVRAMUsageInMB);
32+
33+
// Function to get the ASICFamilyType from the adapter.
34+
// Return ADL_OK on success
35+
extern int ADL2_Adapter_ASICFamilyType_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* lpAsicTypes, int* lpValids);
36+
37+
// Function to retrieve current Overdrive and performance-related activity.
38+
// Return ADL_OK on success
39+
extern int ADL2_Overdrive6_CurrentStatus_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLOD6CurrentStatus* lpCurrentStatus);
40+
41+
// Function to retrieve GPU temperature from the thermal controller.
42+
// Return ADL_OK on success
43+
extern int ADL2_Overdrive6_Temperature_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* lpTemperature);
44+
45+
// Function to retrieve the current or default Overdrive clock ranges.
46+
// Return ADL_OK on success
47+
extern int ADL2_Overdrive6_StateInfo_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int iStateType, ADLOD6StateInfo* lpStateInfo);

src/detection/gpu/gpu_amd.c

Lines changed: 126 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,84 @@
11
#include "gpu_driver_specific.h"
22

3-
// Everything detected in this file is static.
4-
// The real time monitoring requires ADLX, whose interface is much more complicated than AGS
5-
// Whoever has AMD graphic cards interested in this may contribute
6-
// * ADLX (AMD Device Library eXtra): https://github.com/GPUOpen-LibrariesAndSDKs/ADLX
7-
8-
#include "3rdparty/ags/amd_ags.h"
3+
#include "adl.h"
94
#include "common/library.h"
105
#include "util/mallocHelper.h"
116

12-
const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName)
7+
// Memory allocation function
8+
void* __attribute__((__stdcall__)) ADL_Main_Memory_Alloc(int iSize)
139
{
14-
static bool inited = false;
15-
static AGSGPUInfo gpuInfo;
10+
return malloc((size_t) iSize);
11+
}
1612

17-
if (!inited)
13+
struct FFAdlData {
14+
FF_LIBRARY_SYMBOL(ADL2_Main_Control_Destroy)
15+
FF_LIBRARY_SYMBOL(ADL2_Adapter_AdapterInfoX3_Get)
16+
FF_LIBRARY_SYMBOL(ADL2_Adapter_Graphic_Core_Info_Get)
17+
FF_LIBRARY_SYMBOL(ADL2_Adapter_MemoryInfo2_Get)
18+
FF_LIBRARY_SYMBOL(ADL2_Adapter_DedicatedVRAMUsage_Get)
19+
FF_LIBRARY_SYMBOL(ADL2_Adapter_VRAMUsage_Get)
20+
FF_LIBRARY_SYMBOL(ADL2_Adapter_ASICFamilyType_Get)
21+
FF_LIBRARY_SYMBOL(ADL2_Overdrive6_CurrentStatus_Get)
22+
FF_LIBRARY_SYMBOL(ADL2_Overdrive6_Temperature_Get)
23+
FF_LIBRARY_SYMBOL(ADL2_Overdrive6_StateInfo_Get)
24+
25+
bool inited;
26+
ADL_CONTEXT_HANDLE apiHandle;
27+
} adlData;
28+
29+
static void shutdownAdl()
30+
{
31+
if (adlData.apiHandle)
1832
{
19-
inited = true;
20-
FF_LIBRARY_LOAD(libags, "dlopen amd_ags failed", soName , 1);
21-
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libags, agsInitialize)
22-
23-
struct AGSContext* apiHandle;
24-
if (ffagsInitialize(AGS_CURRENT_VERSION, NULL, &apiHandle, &gpuInfo) != AGS_SUCCESS)
25-
return "loading ags library failed";
33+
adlData.ffADL2_Main_Control_Destroy(adlData.apiHandle);
34+
adlData.apiHandle = NULL;
35+
}
36+
}
2637

27-
// agsDeInitialize will free pointers allocated in gpuInfo. Just leak them.
38+
const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName)
39+
{
40+
if (!adlData.inited)
41+
{
42+
adlData.inited = true;
43+
FF_LIBRARY_LOAD(atiadl, "dlopen atiadlxx failed", soName , 1);
44+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(atiadl, ADL2_Main_Control_Create)
45+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Main_Control_Destroy)
46+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_AdapterInfoX3_Get)
47+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_Graphic_Core_Info_Get)
48+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_MemoryInfo2_Get)
49+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_DedicatedVRAMUsage_Get)
50+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_VRAMUsage_Get)
51+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_ASICFamilyType_Get)
52+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_CurrentStatus_Get)
53+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_Temperature_Get)
54+
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_StateInfo_Get)
55+
56+
if (ffADL2_Main_Control_Create(ADL_Main_Memory_Alloc, 1 /*iEnumConnectedAdapters*/, &adlData.apiHandle) != ADL_OK)
57+
return "ffADL2_Main_Control_Create() failed";
58+
59+
atexit(shutdownAdl);
60+
atiadl = NULL; // don't close atiadl
2861
}
2962

30-
if (gpuInfo.numDevices == 0)
31-
return "loading ags library failed or no AMD gpus found";
63+
if (!adlData.apiHandle)
64+
return "ffADL2_Main_Control_Create() failed";
3265

33-
AGSDeviceInfo* device = NULL;
66+
FF_AUTO_FREE AdapterInfo* devices = NULL;
67+
int numDevices = 0;
68+
if (adlData.ffADL2_Adapter_AdapterInfoX3_Get(adlData.apiHandle, -1, &numDevices, &devices) == 0)
69+
return "ffADL2_Adapter_AdapterInfoX3_Get() failed";
3470

35-
for (int iDev = 0; iDev < gpuInfo.numDevices; iDev++)
71+
const AdapterInfo* device = NULL;
72+
for (int iDev = 0; iDev < numDevices; iDev++)
3673
{
37-
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID)
74+
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
3875
{
3976
if (
40-
cond->pciDeviceId.deviceId == (uint32_t) gpuInfo.devices[iDev].deviceId &&
41-
cond->pciDeviceId.vendorId == (uint32_t) gpuInfo.devices[iDev].vendorId &&
42-
cond->pciDeviceId.revId == (uint32_t) gpuInfo.devices[iDev].revisionId)
77+
cond->pciBusId.bus == (uint32_t) devices[iDev].iBusNumber &&
78+
cond->pciBusId.device == (uint32_t) devices[iDev].iDeviceNumber &&
79+
cond->pciBusId.func == (uint32_t) devices[iDev].iFunctionNumber)
4380
{
44-
device = &gpuInfo.devices[iDev];
81+
device = &devices[iDev];
4582
break;
4683
}
4784
}
@@ -51,25 +88,80 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
5188
return "Device not found";
5289

5390
if (result.coreCount)
54-
*result.coreCount = (uint32_t) device->numCUs;
91+
{
92+
ADLGraphicCoreInfo coreInfo;
93+
if (adlData.ffADL2_Adapter_Graphic_Core_Info_Get(adlData.apiHandle, device->iAdapterIndex, &coreInfo) == ADL_OK)
94+
*result.coreCount = (uint32_t) coreInfo.iNumCUs;
95+
}
5596

5697
if (result.memory)
5798
{
58-
result.memory->total = device->localMemoryInBytes;
59-
result.memory->used = FF_GPU_VMEM_SIZE_UNSET;
99+
int vramUsage = 0;
100+
if (adlData.ffADL2_Adapter_DedicatedVRAMUsage_Get(adlData.apiHandle, device->iAdapterIndex, &vramUsage) == ADL_OK)
101+
result.memory->used = (uint64_t) vramUsage * 1024 * 1024;
102+
if (result.sharedMemory)
103+
{
104+
vramUsage = 0;
105+
if (adlData.ffADL2_Adapter_VRAMUsage_Get(adlData.apiHandle, device->iAdapterIndex, &vramUsage) == ADL_OK)
106+
result.sharedMemory->used = (uint64_t) vramUsage * 1024 * 1024 - result.memory->used;
107+
}
108+
}
109+
110+
if (result.memoryType)
111+
{
112+
ADLMemoryInfo2 memoryInfo;
113+
if (adlData.ffADL2_Adapter_MemoryInfo2_Get(adlData.apiHandle, device->iAdapterIndex, &memoryInfo) == ADL_OK)
114+
ffStrbufSetS(result.memoryType, memoryInfo.strMemoryType);
60115
}
61116

62117
if (result.frequency)
63-
*result.frequency = (uint32_t) device->coreClock; // Maximum frequency
118+
{
119+
ADLOD6StateInfo stateInfo;
120+
if (adlData.ffADL2_Overdrive6_StateInfo_Get(adlData.apiHandle, device->iAdapterIndex, ADL_OD6_GETSTATEINFO_CUSTOM_PERFORMANCE, &stateInfo) == ADL_OK)
121+
{
122+
int clock = 0; // assume in 10 kHz
123+
for (int i = 0; i < stateInfo.iNumberOfPerformanceLevels; i++)
124+
{
125+
if (stateInfo.aLevels[i].iEngineClock > clock)
126+
clock = stateInfo.aLevels[i].iEngineClock;
127+
}
128+
*result.frequency = (uint32_t) clock / 100;
129+
}
130+
}
131+
132+
if (result.coreUsage)
133+
{
134+
ADLOD6CurrentStatus status;
135+
if (adlData.ffADL2_Overdrive6_CurrentStatus_Get(adlData.apiHandle, device->iAdapterIndex, &status) == ADL_OK)
136+
{
137+
if (result.coreUsage)
138+
*result.coreUsage = status.iActivityPercent;
139+
}
140+
}
64141

65142
if (result.type)
66-
*result.type = device->isAPU ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
143+
{
144+
int asicTypes = 0;
145+
int valids = 0;
146+
if (adlData.ffADL2_Adapter_ASICFamilyType_Get(adlData.apiHandle, device->iAdapterIndex, &asicTypes, &valids) == ADL_OK)
147+
{
148+
asicTypes &= valids; // This design is strange
149+
*result.type = asicTypes & ADL_ASIC_INTEGRATED ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
150+
}
151+
}
67152

68153
if (result.index)
69-
*result.index = (uint32_t) device->adlAdapterIndex;
154+
*result.index = (uint32_t) device->iAdapterIndex;
70155

71156
if (result.name)
72-
ffStrbufSetS(result.name, device->adapterString);
157+
ffStrbufSetS(result.name, device->strAdapterName);
158+
159+
if (result.temp)
160+
{
161+
int milliDegrees = 0;
162+
if (adlData.ffADL2_Overdrive6_Temperature_Get(adlData.apiHandle, device->iAdapterIndex, &milliDegrees) == ADL_OK)
163+
*result.temp = milliDegrees / 1000.0;
164+
}
73165

74166
return NULL;
75167
}

src/detection/gpu/gpu_driver_specific.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ FF_MAYBE_UNUSED static inline bool getDriverSpecificDetectionFn(const char* vend
8989
{
9090
*pDetectFn = ffDetectAmdGpuInfo;
9191
#ifdef _WIN64
92-
*pDllName = "amd_ags_x64.dll";
92+
*pDllName = "atiadlxx.dll";
9393
#else
94-
*pDllName = "amd_ags_x86.dll";
94+
*pDllName = "atiadlxy.dll";
9595
#endif
9696
}
9797
#endif

0 commit comments

Comments
 (0)