Cypheros System Info Tool (Temperatur und Auslastung)

Begonnen von Cypheros, Oktober 01, 2020, 23:21:43

« vorheriges - nächstes »

Cypheros

Ja, das habe ich auch schon bemerkt.  ;)
Versionen 5,6,7 bzw. Overdrive5, Overdrive6, OverdriveN werden bereits unterstützt. AMD ist bei den Treibern und APIs eine echte Zumutung.

Bei Overdrive8 habe ich noch keine Samples für Temperatur und Usage gefunden. Windows selbst scheint die GPU-Usage sowieso über die undokumentierte Funktion D3DKMTQueryStatistics in der GDI32.dll zu gewinnen, was ich ebenfalls als Fallback benutze.

Mam

#16
Zitat von: Cypheros am Oktober 04, 2020, 23:08:35
Ja, das habe ich auch schon bemerkt.  ;)
Versionen 5,6,7 bzw. Overdrive5, Overdrive6, OverdriveN werden bereits unterstützt. AMD ist bei den Treibern und APIs eine echte Zumutung.

Bei Overdrive8 habe ich noch keine Samples für Temperatur und Usage gefunden. Windows selbst scheint die GPU-Usage sowieso über die undokumentierte Funktion D3DKMTQueryStatistics in der GDI32.dll zu gewinnen, was ich ebenfalls als Fallback benutze.
Nimm meinen Link, da findest Du ein Sample namens "Overdrive8". Das funktioniert auch (aber eben total anders).
Ich geb zu, die Treiber sind echter Mist. Nicht nur intern, auch die Benutzeroberfläche ist ne Zumutung. Kann sein, dass es demnächst wieder was total Neues gibt, wir (die Usah) haben AMD langsam weichgeklopft, wir wollen wieder einen schlanken Treiber haben und nicht dieses ganze Geraffel (>400Mb) von Bloatware.
Ach ja, kleine Warnung: Es gibt nicht "DIE" Temperatur, sondern deren viele! Wie bei CPU gibt es Messungen im Chipcarrier und im Chip selber (natürlich höher). Schon bei der CPU zeigst Du eigentlich die falsche an. Ist aber Verhandlungssache, nur, bei der GPU sollte dann auch derselbe Wert gezeigt werden.



Cypheros

Ja, AMD weiß wirklich wie man es kompliziert macht.

ADL2_New_QueryPMLogData_Get scheint die Zauberfunktion zu sein, mit der man den neuen Navi 14+ einige Parameter entlocken kann. Leider hab ich kein derartige Karte hier und kann das nicht testen.

Mam

#18
Zitat von: Cypheros am Oktober 05, 2020, 09:32:59
Ja, AMD weiß wirklich wie man es kompliziert macht.

ADL2_New_QueryPMLogData_Get scheint die Zauberfunktion zu sein, mit der man den neuen Navi 14+ einige Parameter entlocken kann. Leider hab ich kein derartige Karte hier und kann das nicht testen.
Jo, das ist der richtige Weg.
Update: Nö, doch nicht  :o GuckstDu:
Zitatint ADL2_Overdrive8_Current_Setting_Get    (    ADL_CONTEXT_HANDLE     context,
      int     iAdapterIndex,
      ADLOD8CurrentSetting *     lpCurrentSetting   
   )          

Function to retrieve the Overdrive8 current settings.

This function retrieves the Overdrive8 current settings for a specified adapter.

Supported Platforms:
    Windows (XP, Vista and above); 32bit and 64bit

Parameters:
    [in]    context,:    Client's ADL context handle ADL_CONTEXT_HANDLE obtained from ADL2_Main_Control_Create.
    [in]    iAdapterIndex    The ADL index handle of the desired adapter.
    [out]    lpCurrentSetting    The pointer to the current settings structure storing the retrieved Overdrive parameters.

Returns:
    If the function succeeds, the return value is ADL_OK. Otherwise the return value is an ADL error code. Result Codes

Remarks:
    Clients can use ADL2 version of the API to assure that there is no interference with other ADL clients that are running in the same process . Such clients have to call ADL2_Main_Control_Create first to obtain ADL_CONTEXT_HANDLE instance that has to be passed to each subsequent ADL2 call and finally destroyed using ADL2_Main_Control_Destroy.

Deprecated:
    This API has been deprecated.

Examples:
    Overdrive8/Overdrive8.cpp.

Mach trotzdem rein und schick rüber :-)
Ich such denn mal weiter, was offiziell nun wirklich "IN" sein sollte ;D

Offensichtlich sind viele Felder optional und werden nicht von jeder Karte bedient. Du musst also jedesmal gucken, ob die Abfrage eines Wertes überhaupt erlaubt ist / es den Wert überhaupt gibt.
Hat sich wohl einer ausgedacht, der die Schuhe mit der Kneifzange zumacht, sorry :-(

Was mich beim Durchstöbern der Doku am meisten traurig macht: MAN KANN DIE WERTE AUCH EINFACH ÄNDERN!!!
Wenn ich dem User also was Böses will, dann schalte ich die Lüfter ab, setze die Spannung auf Maximum hoch und lasse die Karte brutzeln...
Und das alles ohne irgendeine Sicherheitsabfrage / Sperre...
SEEEHR BEDENKLICH, da fallen mir nette Erpressungstrojaner ein: "Zahlen Sie X Bitcoins, sonst brennt Ihr Computer ab!"

Cypheros

Nein, damit kriege ich nur die Einstellungen, nicht die Sensoren.

Hiermit scheint man die Sensoren abfragen zu können:

                //make ADL call for VEGA12
                ADLPMLogDataOutput odlpDataOutput;
                memset(&odlpDataOutput, 0, sizeof(ADLPMLogDataOutput));
                ret = ADL2_New_QueryPMLogData_Get(context, lpAdapterInfo[i].iAdapterIndex, &odlpDataOutput);
                if (0 == ret)
                {
                    if (((odInitSetting.overdrive8Capabilities &  ADL_OD8_TEMPERATURE_SYSTEM) == ADL_OD8_TEMPERATURE_SYSTEM) ||
                        ((odInitSetting.overdrive8Capabilities &  ADL_OD8_TEMPERATURE_FAN) == ADL_OD8_TEMPERATURE_FAN) ||
                        ((odInitSetting.overdrive8Capabilities &  ADL_OD8_POWER_LIMIT) == ADL_OD8_POWER_LIMIT))
                    {
                        OverdriveRangeDataStruct oneRangeData;
                        GetOD8RangePrint(odInitSetting, odCurrentSetting, oneRangeData, OD8_OPERATING_TEMP_MAX, ADL_OD8_TEMPERATURE_SYSTEM);
                        GetOD8RangePrint(odInitSetting, odCurrentSetting, oneRangeData, OD8_FAN_TARGET_TEMP, ADL_OD8_TEMPERATURE_FAN);
                        GetOD8RangePrint(odInitSetting, odCurrentSetting, oneRangeData, OD8_POWER_PERCENTAGE, ADL_OD8_POWER_LIMIT);

                        PRINTF("ADLSensorType: PMLOG_TEMPERATURE_EDGE - Current Temp\n");
                        PRINTF("PMLOG_TEMPERATURE_EDGE.supported:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_EDGE].supported);
                        PRINTF("PMLOG_TEMPERATURE_EDGE.value:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_EDGE].value);

                        PRINTF("ADLSensorType: PMLOG_TEMPERATURE_HOTSPOT - Junction Temp\n");
                        PRINTF("PMLOG_TEMPERATURE_HOTSPOT.supported:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_HOTSPOT].supported);
                        PRINTF("PMLOG_TEMPERATURE_HOTSPOT.value:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_HOTSPOT].value);

PRINTF("ADLSensorType: PMLOG_TEMPERATURE_MEM - Memory Temp\n");
PRINTF("PMLOG_TEMPERATURE_MEM.supported:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_MEM].supported);
PRINTF("PMLOG_TEMPERATURE_MEM.value:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_MEM].value);
                        PRINTF("-----------------------------------------\n");

                    }
                    else
                        PRINTF("OD8 Failed to get Temperature Settings\n");



Das hier scheint das zu sein, was wir brauchen: ADLPMLogDataOutput structure storing the retrieved performance metrics parameters.

int ADL2_New_QueryPMLogData_Get ( ADL_CONTEXT_HANDLE  context,
int  iAdapterIndex,
ADLPMLogDataOutput *  lpDataOutput
)

Function to retrieve the Overdrive8 current settings.

This function retrieves the Overdrive8 current settings for a specified adapter.

Supported Platforms:
    Windows (XP, Vista and above); 32bit and 64bit

Parameters:
    [in] context,: Client's ADL context handle ADL_CONTEXT_HANDLE obtained from ADL2_Main_Control_Create.
    [in] iAdapterIndex The ADL index handle of the desired adapter.
    [out] lpDataOutput The pointer to the ADLPMLogDataOutput structure storing the retrieved performance metrics parameters.

Returns:
    If the function succeeds, the return value is ADL_OK. Otherwise the return value is an ADL error code. Result Codes

Remarks:
    Clients can use ADL2 version of the API to assure that there is no interference with other ADL clients that are running in the same process . Such clients have to call ADL2_Main_Control_Create first to obtain ADL_CONTEXT_HANDLE instance that has to be passed to each subsequent ADL2 call and finally destroyed using ADL2_Main_Control_Destroy.

Deprecated:
    This API has been deprecated.

Examples:
    Overdrive8/Overdrive8.cpp.


Mam

Zitat von: Cypheros am Oktober 05, 2020, 12:15:41
Nein, damit kriege ich nur die Einstellungen, nicht die Sensoren.
Jein  ;D
Du brauchst den Call um festzustellen, ob ein Sensor überhaupt existiert. Ansonsten ist nix mit Auslesen der Werte.

Aber egal, mach, was Du möchstest. Es scheint ja eh nur eine temporäre "Lösung" zu geben, da ALLE Calls wohl als "deprecated" geführt werden.
Entweder ist das ein Cut&Pastefehler bei AMD, oder die haben schon wieder was Neues in der Röhre...

Cypheros

AGS is comming: https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/

Ich mach mal eine Routine, die die 32 Parameter einfach ins Log packt bei OD8-Karten. Dann sehen wir ja, was davon brauchbare Werte enthält und was nicht.

Mam

#22
Zitat von: Cypheros am Oktober 05, 2020, 14:49:39
AGS is comming: https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/

Ich mach mal eine Routine, die die 32 Parameter einfach ins Log packt bei OD8-Karten. Dann sehen wir ja, was davon brauchbare Werte enthält und was nicht.

Hmm AGS wird bei Dir nicht zielführend sein, das sind nur Treibereinstellungen, keine Betriebsdaten. Du wirst wohl doch Overdrive8 klauen müssen und die If Abfrage um die Version eränzen (oder doch mal langsam zu "case..." greifen)


Cypheros

Hab dir den Link für die Testversion mit Overdrive 8 Sensor-Dump geschickt.

Mam

#24
Zitat von: Cypheros am Oktober 05, 2020, 18:45:27
Hab dir den Link für die Testversion mit Overdrive 8 Sensor-Dump geschickt.
Das war ein Griff ins Klo, üb nochmal, das Programm lässt sich gar nicht erstmal starten...
Name der fehlerhaften Anwendung: CySysInfo.exe, Version: 0.5.4.0, Zeitstempel: 0x5f7b4a1d
Name des fehlerhaften Moduls: CySysInfo.exe, Version: 0.5.4.0, Zeitstempel: 0x5f7b4a1d
Ausnahmecode: 0xc0000005
Fehleroffset: 0x0000000000701322
ID des fehlerhaften Prozesses: 0x2b78
Startzeit der fehlerhaften Anwendung: 0x01d69b3795a5e299
Pfad der fehlerhaften Anwendung: D:\Incoming\CySysInfo.exe
Pfad des fehlerhaften Moduls: D:\Incoming\CySysInfo.exe
Berichtskennung: c6802a3d-0d9f-4b84-bb77-c59de2ed1a6e
Vollständiger Name des fehlerhaften Pakets:
Anwendungs-ID, die relativ zum fehlerhaften Paket ist:


Ach ja, bevor ichs vergesse: Wenn Dein Progrämmchen mal wieder den "el Condor pasa" gemacht hat (hatte die erste Version auch schon geschafft), verbleibt ein Lock auf "winRing0x64.sys" im Speicher. Lässt sich nicht löschen oder verschieben. Ist also trotz Abflug ein Handle offen. Ich nehme aber an, das Teil wird von der DLL nachgeladen und gehört nich direkt zur Prozessgruppe Deines Tasks.
Hilft nur ein Reboot.

Mam

also, ich war mal gnädig und hab Dir das Sample "so klein wie möglich" gemacht und nur die Ausleseroutine für die Temperaturen übrig gelassen (ist noch ein wenig Müll drin, aber lohnt nicht wirklich ihn zu entsorgen)
Beispieloutput ist:

Gefunden: 8 Grafikkarten
-----------------------------------------
Adapter Index[0]
-----------------------------------------
itemID:OD8_OPERATING_TEMP_MAX: is not Visible
OD8_OPERATING_TEMP_MAX:maxValue:0
minValue:0
defaultValue:0
-----------------------------------------
itemID:OD8_FAN_TARGET_TEMP: is not Visible
OD8_FAN_TARGET_TEMP:maxValue:100
minValue:25
defaultValue:90
-----------------------------------------
itemID:OD8_POWER_PERCENTAGE: is Visible
actualValue:0
OD8_POWER_PERCENTAGE:maxValue:50
minValue:-50
defaultValue:0
-----------------------------------------
ADLSensorType: PMLOG_TEMPERATURE_EDGE - Current Temp
PMLOG_TEMPERATURE_EDGE.supported:1
PMLOG_TEMPERATURE_EDGE.value:34
ADLSensorType: PMLOG_TEMPERATURE_HOTSPOT - Junction Temp
PMLOG_TEMPERATURE_HOTSPOT.supported:1
PMLOG_TEMPERATURE_HOTSPOT.value:34
ADLSensorType: PMLOG_TEMPERATURE_MEM - Memory Temp
PMLOG_TEMPERATURE_MEM.supported:1
PMLOG_TEMPERATURE_MEM.value:40
-----------------------------------------
ENDE!

die drei Temperaturen sind ja eindeutig zu erkennen und die dazugehörigen DEFINES ebenfalls. Wobei EDGE die Carrier Temperatur ist und Junction die Temperatur des Chips (MEM ist ja wohl klar, oder?).

Aber Achtung! jede Karte sind mindestens 8 Devices! Das läuft also in einer Schleife. Wahrscheinlich gibts mehr Karten, wenn man mehr Monitore anschliesst, aber mir reicht mein 37" 4K Monitörchen :-)

Ich pack mal den Quelltext hier rein (Du brauchst noch die drei Headerfiles aus dem INCLUDE Verzeichnis der Samples)


// OD8Test.cpp : Diese Datei enthält die Funktion "main". Hier beginnt und endet die Ausführung des Programms.
//

#include <iostream>
#include <windows.h>
#include "adl_sdk.h"
#include "adl_structures.h"
#include <stdio.h>

#define PRINTF printf

struct OverdriveRangeDataStruct
{
    //Minimum value
    int Min_;
    //Maximum value
    int Max_;
    //Expected value: similar to current value
    int ExpectedValue_;
    //Default value
    int DefaultValue_;
    //Actual value
    int ActualValue_;
    // If ActualValue can be got from the driver, ActualValueAvailable_ will be true
    bool ActualValueAvailable_;
    // If the disable/enable feature is supported by the driver, it is true.
    bool EnableDisableSupport_;
    // The enabled state
    bool Visible_;
};

char* sensorType[] = {
(char*) "SENSOR_MAXTYPES",
(char*) "PMLOG_CLK_GFXCLK",
(char*) "PMLOG_CLK_MEMCLK",
(char*) "PMLOG_CLK_SOCCLK",
(char*) "PMLOG_CLK_UVDCLK1",
(char*) "PMLOG_CLK_UVDCLK2",
(char*) "PMLOG_CLK_VCECLK",
(char*) "PMLOG_CLK_VCNCLK",
(char*) "PMLOG_TEMPERATURE_EDGE",
(char*) "PMLOG_TEMPERATURE_MEM",
(char*) "PMLOG_TEMPERATURE_VRVDDC",
(char*) "PMLOG_TEMPERATURE_VRMVDD",
(char*) "PMLOG_TEMPERATURE_LIQUID",
(char*) "PMLOG_TEMPERATURE_PLX",
(char*) "PMLOG_FAN_RPM",
(char*) "PMLOG_FAN_PERCENTAGE",
(char*) "PMLOG_SOC_VOLTAGE",
(char*) "PMLOG_SOC_POWER",
(char*) "PMLOG_SOC_CURRENT",
(char*) "PMLOG_INFO_ACTIVITY_GFX",
(char*) "PMLOG_INFO_ACTIVITY_MEM",
(char*) "PMLOG_GFX_VOLTAGE",
(char*) "PMLOG_MEM_VOLTAGE",
(char*) "PMLOG_ASIC_POWER",
(char*) "PMLOG_TEMPERATURE_VRSOC",
(char*) "PMLOG_TEMPERATURE_VRMVDD0",
(char*) "PMLOG_TEMPERATURE_VRMVDD1",
(char*) "PMLOG_TEMPERATURE_HOTSPOT"
};
int PrintFeatureName(int itemID_)
{
    switch (itemID_)
    {
    case OD8_GFXCLK_FREQ1:
        PRINTF("OD8_GFXCLK_FREQ1:");
        break;
    case OD8_GFXCLK_FREQ2:
        PRINTF("OD8_GFXCLK_FREQ2:");
        break;
    case OD8_GFXCLK_FREQ3:
        PRINTF("OD8_GFXCLK_FREQ3:");
        break;
    case OD8_GFXCLK_FMIN:
        PRINTF("OD8_GFXCLK_FMIN:");
        break;
    case OD8_GFXCLK_FMAX:
        PRINTF("OD8_GFXCLK_FMAX:");
        break;
    case OD8_GFXCLK_VOLTAGE1:
        PRINTF("OD8_GFXCLK_VOLTAGE1:");
        break;
    case OD8_GFXCLK_VOLTAGE2:
        PRINTF("OD8_GFXCLK_VOLTAGE2:");
        break;
    case OD8_GFXCLK_VOLTAGE3:
        PRINTF("OD8_GFXCLK_VOLTAGE3:");
        break;
    case OD8_UCLK_FMAX:
        PRINTF("OD8_UCLK_FMAX:");
        break;
    case OD8_OPERATING_TEMP_MAX:
        PRINTF("OD8_OPERATING_TEMP_MAX:");
        break;
    case OD8_FAN_TARGET_TEMP:
        PRINTF("OD8_FAN_TARGET_TEMP:");
        break;
    case OD8_POWER_PERCENTAGE:
        PRINTF("OD8_POWER_PERCENTAGE:");
        break;
    case OD8_FAN_MIN_SPEED:
        PRINTF("OD8_FAN_MIN_SPEED:");
        break;
    case OD8_FAN_ACOUSTIC_LIMIT:
        PRINTF("OD8_FAN_ACOUSTIC_LIMIT:");
        break;
    case OD8_AC_TIMING:
        PRINTF("OD8_AC_TIMING:");
        break;
    case OD8_FAN_ZERORPM_CONTROL:
        PRINTF("OD8_FAN_ZERORPM_CONTROL:");
        break;
    case OD8_FAN_CURVE_TEMPERATURE_1:
        PRINTF("OD8_FAN_CURVE_TEMPERATURE_1:");
        break;
    case OD8_FAN_CURVE_SPEED_1:
        PRINTF("OD8_FAN_CURVE_SPEED_1:");
        break;
    case OD8_FAN_CURVE_TEMPERATURE_2:
        PRINTF("OD8_FAN_CURVE_TEMPERATURE_2:");
        break;
    case OD8_FAN_CURVE_SPEED_2:
        PRINTF("OD8_FAN_CURVE_SPEED_2:");
        break;
    case OD8_FAN_CURVE_TEMPERATURE_3:
        PRINTF("OD8_FAN_CURVE_TEMPERATURE_3:");
        break;
    case OD8_FAN_CURVE_SPEED_3:
        PRINTF("OD8_FAN_CURVE_SPEED_3:");
        break;
    case OD8_FAN_CURVE_TEMPERATURE_4:
        PRINTF("OD8_FAN_CURVE_TEMPERATURE_4:");
        break;
    case OD8_FAN_CURVE_SPEED_4:
        PRINTF("OD8_FAN_CURVE_SPEED_4 = 26:");
        break;
    case OD8_FAN_CURVE_TEMPERATURE_5:
        PRINTF("OD8_FAN_CURVE_TEMPERATURE_5:");
        break;
    case OD8_FAN_CURVE_SPEED_5:
        PRINTF("OD8_FAN_CURVE_SPEED_5:");
        break;
    case OD8_POWER_GAUGE:
        PRINTF("OD8_POWER_GAUGE:");
        break;
    default:
        PRINTF("Found no featureID \n");
        return ADL_ERR;
    }
    return ADL_OK;
}

// Definitions of the used function pointers. Add more if you use other ADL APIs
typedef int(*ADL_MAIN_CONTROL_CREATE)(ADL_MAIN_MALLOC_CALLBACK, int);
typedef int(*ADL_MAIN_CONTROL_DESTROY)();
typedef int(*ADL_ADAPTER_NUMBEROFADAPTERS_GET) (int*);
typedef int(*ADL_ADAPTER_ADAPTERINFO_GET) (LPAdapterInfo, int);
typedef int(*ADL_ADAPTERX2_CAPS) (int, int*);
typedef int(*ADL2_ADAPTER_ACTIVE_GET) (ADL_CONTEXT_HANDLE, int, int*);
typedef int(*ADL2_OVERDRIVE_CAPS) (ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iSupported, int* iEnabled, int* iVersion);
typedef int(*ADL2_ADAPTER_REGVALUEINT_GET) (ADL_CONTEXT_HANDLE context, int iAdapterIndex, int iDriverPathOption, const char* szSubKey, const char* szKeyName, int* lpKeyValue);

typedef int(*ADL2_OVERDRIVE8_INIT_SETTING_GET) (ADL_CONTEXT_HANDLE, int, ADLOD8InitSetting*);
typedef int(*ADL2_OVERDRIVE8_CURRENT_SETTING_GET) (ADL_CONTEXT_HANDLE, int, ADLOD8CurrentSetting*);
typedef int(*ADL2_OVERDRIVE8_SETTING_SET) (ADL_CONTEXT_HANDLE, int, ADLOD8SetSetting*, ADLOD8CurrentSetting*);
typedef int(*ADL2_NEW_QUERYPMLOGDATA_GET) (ADL_CONTEXT_HANDLE, int, ADLPMLogDataOutput*);

typedef int(*ADL2_OVERDRIVE8_INIT_SETTINGX2_GET) (ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* lpOverdrive8Capabilities, int* lpNumberOfFeatures, ADLOD8SingleInitSetting** lppInitSettingList);
typedef int(*ADL2_OVERDRIVE8_CURRENT_SETTINGX2_GET) (ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* lpNumberOfFeatures, int** lppCurrentSettingList);


typedef int(*ADL2_ADAPTER_PMLOG_SUPPORT_GET) (ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLPMLogSupportInfo* pPMLogSupportInfo);
typedef int(*ADL2_ADAPTER_PMLOG_SUPPORT_START) (ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLPMLogStartInput* pPMLogStartInput, ADLPMLogStartOutput* pPMLogStartOutput, ADL_D3DKMT_HANDLE pDevice);
typedef int(*ADL2_ADAPTER_PMLOG_SUPPORT_STOP) (ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADL_D3DKMT_HANDLE pDevice);
typedef int(*ADL2_DESKTOP_DEVICE_CREATE) (ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADL_D3DKMT_HANDLE* pDevice);
typedef int(*ADL2_DESKTOP_DEVICE_DESTROY) (ADL_CONTEXT_HANDLE context, ADL_D3DKMT_HANDLE hDevice);
HINSTANCE hDLL;

ADL_MAIN_CONTROL_CREATE          ADL_Main_Control_Create = NULL;
ADL_MAIN_CONTROL_DESTROY         ADL_Main_Control_Destroy = NULL;
ADL_ADAPTER_NUMBEROFADAPTERS_GET ADL_Adapter_NumberOfAdapters_Get = NULL;
ADL_ADAPTER_ADAPTERINFO_GET      ADL_Adapter_AdapterInfo_Get = NULL;
ADL_ADAPTERX2_CAPS               ADL_AdapterX2_Caps = NULL;
ADL2_ADAPTER_ACTIVE_GET          ADL2_Adapter_Active_Get = NULL;
ADL2_OVERDRIVE_CAPS              ADL2_Overdrive_Caps = NULL;
ADL2_ADAPTER_REGVALUEINT_GET     ADL2_Adapter_RegValueInt_Get = NULL;

ADL2_OVERDRIVE8_INIT_SETTING_GET ADL2_Overdrive8_Init_Setting_Get = NULL;
ADL2_OVERDRIVE8_CURRENT_SETTING_GET ADL2_Overdrive8_Current_Setting_Get = NULL;
ADL2_OVERDRIVE8_SETTING_SET ADL2_Overdrive8_Setting_Set = NULL;
ADL2_NEW_QUERYPMLOGDATA_GET ADL2_New_QueryPMLogData_Get = NULL;

ADL2_OVERDRIVE8_INIT_SETTINGX2_GET ADL2_Overdrive8_Init_SettingX2_Get = NULL;
ADL2_OVERDRIVE8_CURRENT_SETTINGX2_GET ADL2_Overdrive8_Current_SettingX2_Get = NULL;

ADL2_ADAPTER_PMLOG_SUPPORT_GET ADL2_Adapter_PMLog_Support_Get = NULL;
ADL2_ADAPTER_PMLOG_SUPPORT_START ADL2_Adapter_PMLog_Support_Start = NULL;
ADL2_ADAPTER_PMLOG_SUPPORT_STOP ADL2_Adapter_PMLog_Support_Stop = NULL;
ADL2_DESKTOP_DEVICE_CREATE ADL2_Desktop_Device_Create = NULL;
ADL2_DESKTOP_DEVICE_DESTROY ADL2_Desktop_Device_Destroy = NULL;


// Memory allocation function
void* __stdcall ADL_Main_Memory_Alloc(int iSize)
{
    void* lpBuffer = malloc(iSize);
    return lpBuffer;
}

// Optional Memory de-allocation function
void __stdcall ADL_Main_Memory_Free(void** lpBuffer)
{
    if (NULL != *lpBuffer)
    {
        free(*lpBuffer);
        *lpBuffer = NULL;
    }
}

ADL_CONTEXT_HANDLE context = NULL;
LPAdapterInfo   lpAdapterInfo = NULL;
int  iNumberAdapters;
int initializeADL()
{

    // Load the ADL dll
    hDLL = LoadLibrary(TEXT("atiadlxx.dll"));
    if (hDLL == NULL)
    {
        // A 32 bit calling application on 64 bit OS will fail to LoadLibrary.
        // Try to load the 32 bit library (atiadlxy.dll) instead
        hDLL = LoadLibrary(TEXT("atiadlxy.dll"));
    }

    if (NULL == hDLL)
    {
        PRINTF("Failed to load ADL library\n");
        return FALSE;
    }
    ADL_Main_Control_Create = (ADL_MAIN_CONTROL_CREATE)GetProcAddress(hDLL, "ADL_Main_Control_Create");
    ADL_Main_Control_Destroy = (ADL_MAIN_CONTROL_DESTROY)GetProcAddress(hDLL, "ADL_Main_Control_Destroy");
    ADL_Adapter_NumberOfAdapters_Get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET)GetProcAddress(hDLL, "ADL_Adapter_NumberOfAdapters_Get");
    ADL_Adapter_AdapterInfo_Get = (ADL_ADAPTER_ADAPTERINFO_GET)GetProcAddress(hDLL, "ADL_Adapter_AdapterInfo_Get");
    ADL_AdapterX2_Caps = (ADL_ADAPTERX2_CAPS)GetProcAddress(hDLL, "ADL_AdapterX2_Caps");
    ADL2_Adapter_Active_Get = (ADL2_ADAPTER_ACTIVE_GET)GetProcAddress(hDLL, "ADL2_Adapter_Active_Get");
    ADL2_Overdrive_Caps = (ADL2_OVERDRIVE_CAPS)GetProcAddress(hDLL, "ADL2_Overdrive_Caps");
    ADL2_Adapter_RegValueInt_Get = (ADL2_ADAPTER_REGVALUEINT_GET)GetProcAddress(hDLL, "ADL2_Adapter_RegValueInt_Get");

    ADL2_Overdrive8_Init_Setting_Get = (ADL2_OVERDRIVE8_INIT_SETTING_GET)GetProcAddress(hDLL, "ADL2_Overdrive8_Init_Setting_Get");
    ADL2_Overdrive8_Current_Setting_Get = (ADL2_OVERDRIVE8_CURRENT_SETTING_GET)GetProcAddress(hDLL, "ADL2_Overdrive8_Current_Setting_Get");
    ADL2_Overdrive8_Setting_Set = (ADL2_OVERDRIVE8_SETTING_SET)GetProcAddress(hDLL, "ADL2_Overdrive8_Setting_Set");
    ADL2_New_QueryPMLogData_Get = (ADL2_NEW_QUERYPMLOGDATA_GET)GetProcAddress(hDLL, "ADL2_New_QueryPMLogData_Get");

    ADL2_Overdrive8_Init_SettingX2_Get = (ADL2_OVERDRIVE8_INIT_SETTINGX2_GET)GetProcAddress(hDLL, "ADL2_Overdrive8_Init_SettingX2_Get");
    ADL2_Overdrive8_Current_SettingX2_Get = (ADL2_OVERDRIVE8_CURRENT_SETTINGX2_GET)GetProcAddress(hDLL, "ADL2_Overdrive8_Current_SettingX2_Get");

    ADL2_Adapter_PMLog_Support_Get = (ADL2_ADAPTER_PMLOG_SUPPORT_GET)GetProcAddress(hDLL, "ADL2_Adapter_PMLog_Support_Get");
    ADL2_Adapter_PMLog_Support_Start = (ADL2_ADAPTER_PMLOG_SUPPORT_START)GetProcAddress(hDLL, "ADL2_Adapter_PMLog_Start");
    ADL2_Adapter_PMLog_Support_Stop = (ADL2_ADAPTER_PMLOG_SUPPORT_STOP)GetProcAddress(hDLL, "ADL2_Adapter_PMLog_Stop");
    ADL2_Desktop_Device_Create = (ADL2_DESKTOP_DEVICE_CREATE)GetProcAddress(hDLL, "ADL2_Desktop_Device_Create");
    ADL2_Desktop_Device_Destroy = (ADL2_DESKTOP_DEVICE_DESTROY)GetProcAddress(hDLL, "ADL2_Desktop_Device_Destroy");

    if (NULL == ADL_Main_Control_Create ||
        NULL == ADL_Main_Control_Destroy ||
        NULL == ADL_Adapter_NumberOfAdapters_Get ||
        NULL == ADL_Adapter_AdapterInfo_Get ||
        NULL == ADL_AdapterX2_Caps ||
        NULL == ADL2_Adapter_Active_Get ||
        NULL == ADL2_Overdrive_Caps ||
        NULL == ADL2_Adapter_RegValueInt_Get ||
        NULL == ADL2_Overdrive8_Init_Setting_Get ||
        NULL == ADL2_Overdrive8_Current_Setting_Get ||
        NULL == ADL2_Overdrive8_Setting_Set ||
        NULL == ADL2_New_QueryPMLogData_Get ||
        NULL == ADL2_Overdrive8_Init_SettingX2_Get ||
        NULL == ADL2_Overdrive8_Current_SettingX2_Get ||
        NULL == ADL2_Adapter_PMLog_Support_Get ||
        NULL == ADL2_Adapter_PMLog_Support_Start ||
        NULL == ADL2_Adapter_PMLog_Support_Stop ||
        NULL == ADL2_Desktop_Device_Create ||
        NULL == ADL2_Desktop_Device_Destroy)
    {
        PRINTF("Failed to get ADL function pointers\n");
        return FALSE;
    }

    if (ADL_OK != ADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1))
    {
        printf("Failed to initialize nested ADL2 context");
        return ADL_ERR;
    }

    return TRUE;
}

void deinitializeADL()
{
    ADL_Main_Control_Destroy();
    if (NULL != hDLL)
    {
        FreeLibrary(hDLL);
        hDLL = NULL;
    }
}
int GetOD8InitSetting(int iAdapterIndex, ADLOD8InitSetting& odInitSetting)
{
    int ret = -1;
    memset(&odInitSetting, 0, sizeof(ADLOD8InitSetting));
    odInitSetting.count = OD8_COUNT;
    int overdrive8Capabilities;
    int numberOfFeatures = OD8_COUNT;
    ADLOD8SingleInitSetting* lpInitSettingList = NULL;
    if (NULL != ADL2_Overdrive8_Init_SettingX2_Get)
    {
        ret = ADL2_Overdrive8_Init_SettingX2_Get(context, iAdapterIndex, &overdrive8Capabilities, &numberOfFeatures, &lpInitSettingList);
        if (0 == ret)
        {
            ret = -1;
            odInitSetting.count = numberOfFeatures > OD8_COUNT ? OD8_COUNT : numberOfFeatures;
            odInitSetting.overdrive8Capabilities = overdrive8Capabilities;
            for (int i = 0; i < odInitSetting.count; i++)
            {
                odInitSetting.od8SettingTable[i].defaultValue = lpInitSettingList[i].defaultValue;
                odInitSetting.od8SettingTable[i].featureID = lpInitSettingList[i].featureID;
                odInitSetting.od8SettingTable[i].maxValue = lpInitSettingList[i].maxValue;
                odInitSetting.od8SettingTable[i].minValue = lpInitSettingList[i].minValue;
            }
            ADL_Main_Memory_Free((void**)&lpInitSettingList);
        }
        else
        {
            PRINTF("ADL2_Overdrive8_Init_SettingX2_Get is failed\n");
            ADL_Main_Memory_Free((void**)&lpInitSettingList);
            return ADL_ERR;
        }
    }
    else
    {
        if (NULL != ADL2_Overdrive8_Init_Setting_Get)
        {
            ret = ADL2_Overdrive8_Init_Setting_Get(context, iAdapterIndex, &odInitSetting);
            if (0 == ret)
                ret = -1;
            else
            {
                PRINTF("ADL2_Overdrive8_Init_Setting_Get is failed\n");
                return ADL_ERR;
            }
        }
    }
    return ADL_OK;
}
int GetOD8CurrentSetting(int iAdapterIndex, ADLOD8CurrentSetting& odCurrentSetting)
{
    int ret = -1;
    memset(&odCurrentSetting, 0, sizeof(ADLOD8CurrentSetting));
    odCurrentSetting.count = OD8_COUNT;

    int numberOfFeaturesCurrent = OD8_COUNT;
    int* lpCurrentSettingList = NULL;
    if (NULL != ADL2_Overdrive8_Current_SettingX2_Get)
    {
        ret = ADL2_Overdrive8_Current_SettingX2_Get(context, iAdapterIndex, &numberOfFeaturesCurrent, &lpCurrentSettingList);
        if (0 == ret)
        {
            ret = -1;
            odCurrentSetting.count = numberOfFeaturesCurrent > OD8_COUNT ? OD8_COUNT : numberOfFeaturesCurrent;
            for (int i = 0; i < odCurrentSetting.count; i++)
            {
                odCurrentSetting.Od8SettingTable[i] = lpCurrentSettingList[i];
            }
            ADL_Main_Memory_Free((void**)&lpCurrentSettingList);
        }
        else
        {
            PRINTF("ADL2_Overdrive8_Current_SettingX2_Get is failed\n");
            ADL_Main_Memory_Free((void**)&lpCurrentSettingList);
            return ADL_ERR;
        }
    }
    else
    {
        if (NULL != ADL2_Overdrive8_Current_Setting_Get)
        {
            ret = ADL2_Overdrive8_Current_Setting_Get(context, iAdapterIndex, &odCurrentSetting);
            if (0 == ret)
                ret = -1;
            else
            {
                PRINTF("ADL2_Overdrive8_Current_Setting_Get is failed\n");
                return ADL_ERR;
            }
        }

    }
    return ADL_OK;
}

int GetOD8RangePrint(ADLOD8InitSetting odInitSetting, ADLOD8CurrentSetting odCurrentSetting, OverdriveRangeDataStruct& oneRangeData, int itemID_, int featureID_)
{
    memset(&oneRangeData, 0, sizeof(OverdriveRangeDataStruct));
    oneRangeData.Max_ = odInitSetting.od8SettingTable[itemID_].maxValue;
    oneRangeData.Min_ = odInitSetting.od8SettingTable[itemID_].minValue;
    oneRangeData.DefaultValue_ = odInitSetting.od8SettingTable[itemID_].defaultValue;
    if (OD8_GFXCLK_FMIN == itemID_ || OD8_GFXCLK_FMAX == itemID_ || OD8_UCLK_FMAX == itemID_ || OD8_AC_TIMING == itemID_ || OD8_FAN_ZERORPM_CONTROL == itemID_
        || OD8_AUTO_UV_ENGINE_CONTROL == itemID_ || OD8_AUTO_OC_ENGINE_CONTROL == itemID_ || OD8_AUTO_OC_MEMORY_CONTROL == itemID_)
        oneRangeData.Visible_ = true;
    else
        oneRangeData.Visible_ = ((odInitSetting.overdrive8Capabilities & featureID_) == featureID_) ? true : false;
    PRINTF("itemID:");
    PrintFeatureName(itemID_);
    if (oneRangeData.Visible_) {
        PRINTF(" is Visible\n");
        oneRangeData.ExpectedValue_ = odCurrentSetting.Od8SettingTable[itemID_];
        PRINTF("actualValue:%d\n", oneRangeData.ExpectedValue_);
    }
    else
        PRINTF(" is not Visible\n");
    PrintFeatureName(itemID_);
    PRINTF("maxValue:%d\n", oneRangeData.Max_);
    PRINTF("minValue:%d\n", oneRangeData.Min_);
    PRINTF("defaultValue:%d\n", oneRangeData.DefaultValue_);
    PRINTF("-----------------------------------------\n");
    return ADL_OK;
}

int printOD8TemperatureSettingParameters()
{
    int i;
    int ret = -1;
    int iSupported = 0, iEnabled = 0, iVersion = 0;

    // Repeat for all available adapters in the system
    for (i = 0; i < iNumberAdapters; i++)
    {
        PRINTF("-----------------------------------------\n");
        PRINTF("Adapter Index[%d]\n ", lpAdapterInfo[i].iAdapterIndex);
        PRINTF("-----------------------------------------\n");
        if (lpAdapterInfo[i].iBusNumber > -1)
        {
            ADL2_Overdrive_Caps(context, lpAdapterInfo[i].iAdapterIndex, &iSupported, &iEnabled, &iVersion);
            if (iVersion == 8)
            {
                //OD8 initial Status
                ADLOD8InitSetting odInitSetting;
                if (ADL_OK != GetOD8InitSetting(lpAdapterInfo[i].iAdapterIndex, odInitSetting))
                {
                    PRINTF("Get Init Setting failed.\n");
                    return ADL_ERR;
                }

                //OD8 Current Status
                ADLOD8CurrentSetting odCurrentSetting;
                if (ADL_OK != GetOD8CurrentSetting(lpAdapterInfo[i].iAdapterIndex, odCurrentSetting))
                {
                    PRINTF("Get Current Setting failed.\n");
                    return ADL_ERR;
                }

                //make ADL call for VEGA12
                ADLPMLogDataOutput odlpDataOutput;
                memset(&odlpDataOutput, 0, sizeof(ADLPMLogDataOutput));
                ret = ADL2_New_QueryPMLogData_Get(context, lpAdapterInfo[i].iAdapterIndex, &odlpDataOutput);
                if (0 == ret)
                {
                    if (((odInitSetting.overdrive8Capabilities & ADL_OD8_TEMPERATURE_SYSTEM) == ADL_OD8_TEMPERATURE_SYSTEM) ||
                        ((odInitSetting.overdrive8Capabilities & ADL_OD8_TEMPERATURE_FAN) == ADL_OD8_TEMPERATURE_FAN) ||
                        ((odInitSetting.overdrive8Capabilities & ADL_OD8_POWER_LIMIT) == ADL_OD8_POWER_LIMIT))
                    {
                        OverdriveRangeDataStruct oneRangeData;
                        GetOD8RangePrint(odInitSetting, odCurrentSetting, oneRangeData, OD8_OPERATING_TEMP_MAX, ADL_OD8_TEMPERATURE_SYSTEM);
                        GetOD8RangePrint(odInitSetting, odCurrentSetting, oneRangeData, OD8_FAN_TARGET_TEMP, ADL_OD8_TEMPERATURE_FAN);
                        GetOD8RangePrint(odInitSetting, odCurrentSetting, oneRangeData, OD8_POWER_PERCENTAGE, ADL_OD8_POWER_LIMIT);

                        PRINTF("ADLSensorType: PMLOG_TEMPERATURE_EDGE - Current Temp\n");
                        PRINTF("PMLOG_TEMPERATURE_EDGE.supported:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_EDGE].supported);
                        PRINTF("PMLOG_TEMPERATURE_EDGE.value:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_EDGE].value);

                        PRINTF("ADLSensorType: PMLOG_TEMPERATURE_HOTSPOT - Junction Temp\n");
                        PRINTF("PMLOG_TEMPERATURE_HOTSPOT.supported:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_HOTSPOT].supported);
                        PRINTF("PMLOG_TEMPERATURE_HOTSPOT.value:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_HOTSPOT].value);

                        PRINTF("ADLSensorType: PMLOG_TEMPERATURE_MEM - Memory Temp\n");
                        PRINTF("PMLOG_TEMPERATURE_MEM.supported:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_MEM].supported);
                        PRINTF("PMLOG_TEMPERATURE_MEM.value:%d\n", odlpDataOutput.sensors[PMLOG_TEMPERATURE_MEM].value);
                        PRINTF("-----------------------------------------\n");

                    }
                    else
                        PRINTF("OD8 Failed to get Temperature Settings\n");
                }
                else
                {
                    PRINTF("ADL2_New_QueryPMLogData_Get is failed\n");
                    return ADL_ERR;
                }
                break;
            }
        }

    }
    return 0;
}

int main()
{
    if (!initializeADL())
    {
        printf("Dumm gelaufen\n");
        exit(1);
    }
    if (ADL_OK != ADL_Adapter_NumberOfAdapters_Get(&iNumberAdapters))
    {
        PRINTF("Cannot get the number of adapters!\n");
        return 0;
    }
    printf("Gefunden: %d Grafikkarten\n", iNumberAdapters);
    if (0 < iNumberAdapters)
    {
        lpAdapterInfo = (LPAdapterInfo)malloc(sizeof(AdapterInfo) * iNumberAdapters);
        if (lpAdapterInfo) memset(lpAdapterInfo, '\0', sizeof(AdapterInfo) * iNumberAdapters);
        // Get the AdapterInfo structure for all adapters in the system
        ADL_Adapter_AdapterInfo_Get(lpAdapterInfo, sizeof(AdapterInfo) * iNumberAdapters);
        printOD8TemperatureSettingParameters();
        ADL_Main_Memory_Free((void**)&lpAdapterInfo);
       
    }
    deinitializeADL();

    std::cout << "ENDE!\n";
}


Cypheros

Neue Version 0.5.6 ist online: https://www.cypheros.de/files/tools/CySysInfo_0_5_Beta.zip

Sollte nun auch mit Radeon RX 5000 Karten mit Overdrive 8 klar kommen.
Für die Temperatur hab ich PMLOG_TEMPERATURE_EDGE genommen und für die Auslastung PMLOG_INFO_ACTIVITY_GFX.

Mam

#27
Yep! alles im grünen Bereich Grosser  ;D

(ich wusste doch, dass Du das hinkriegst (mit ein paar Tritten  ;D:-* )

Allerdings könntest Du die GUI noch etwas relaxen, sie ist hauptsächlich für die GraKa Temp und Auslastung verantwortlich.

Cypheros

Ja, das muss noch optimiert werden.

Das Projekt war gedacht um die geräteübergreifende GUI von Delphi kennen zu lernen, die auf DirectX und OpenGL basiert und sowohl unter Windows, Linux, MacOS, IOS und Android läuft. Erstaunlich wie aufwendig es ist Temperatur-Sensoren auszulesen und die CPU und GPU Belastung zu erkennen.


Mam

#29
Zitat von: Cypheros am Oktober 06, 2020, 00:06:17
Das Projekt war gedacht um die geräteübergreifende GUI von Delphi kennen zu lernen,
Ich dachte, Du wolltest langsam mal eine richtige Programmiersprache lernen  ;D  8)
So von matschigen Müsli hin zu Hardcore-C (ohne ++, das ist nur für Weicheier).
Ich hätte auch noch einen alten Amiga im Angebot, da kannst Du sogar "B" (BCPL) üben!

Und nicht in Vergessenheit geraten lassen: die WinRing0x64.dll / .sys gehört in einen Pfad auf einem lokalen Laufwerk. Da wirst Du um ein Setup Programm nicht rumkommen.

Zitat
Erstaunlich wie aufwendig es ist Temperatur-Sensoren auszulesen und die CPU und GPU Belastung zu erkennen.
Na ja, nach dem ersten Schock gefolgt von weiterem Einlesen klang die Panik doch recht schnell ab. Ist zwar nicht schön und clever, was AMD da gemacht hat, aber doch nachvollziehbar. Die haben anfangs eben nicht damit gerechnet, dass GraKas irgendwann einmal die Komplexität einer schnöden CPU dramatisch übersteigen und ihre APIs immer nur auf Sicht ausgelegt.
Aber die derzeitige ist doch recht erweiterbar, sieht sie doch 8 Devices pro Karte, 16 Karten pro Rechner und variable Register pro Karte vor. Der Nachteil ist dann natürlich, dass es nicht mehr DIE (eine) Temperatur gibt, sondern ganze viele...
Ich weis nicht, ob NVidea da ebensolche Reserven vorgesehen hat. Intel ganz bestimmt nicht :-)


www.cypheros.de