ManualGraphicsTuning

Demonstrates how to control manual graphics tuning when programming with ADLX.

Command Prompts

Command Prompt Description
1 Get GPU frequency and voltage.
2 Get current GPU states.
3 Set GPU states.
M/m Show this menu.
Q/q Quit.

Sample Path

/Samples/CPP/GPUTuning/ManualGraphicsTuning

Code

Copied!

//
// Copyright (c) 2021 - 2023 Advanced Micro Devices, Inc. All rights reserved.
//
//-------------------------------------------------------------------------------------------------


#include "SDK/ADLXHelper/Windows/Cpp/ADLXHelper.h"
#include "SDK/Include/IGPUManualGFXTuning.h"
#include "SDK/Include/IGPUTuning.h"
#include <iostream>

// Use ADLX namespace
using namespace adlx;

// ADLXHelper instance
// No outstanding interfaces from ADLX must exist when ADLX is destroyed.
// Use global variables to ensure validity of the interface.
static ADLXHelper g_ADLXHelp;

// Main menu
void MainMenu(IADLXManualGraphicsTuning1Ptr manualGFXTuning1, IADLXManualGraphicsTuning2Ptr manualGFXTuning2);

// Menu action control
void MenuControl(IADLXManualGraphicsTuning1Ptr manualGFXTuning1, IADLXManualGraphicsTuning2Ptr manualGFXTuning2);

// Wait for exit with error message
int WaitAndExit(const char* msg, const int retCode);

/***** The first is pre-Navi, the second is post-Navi *****/
// Display GPU frequency and voltage range
void ShowFrequencyAndVoltageRange(IADLXManualGraphicsTuning1Ptr manualGFXTuning1);
void ShowFrequencyAndVoltageRange(IADLXManualGraphicsTuning2Ptr manualGFXTuning2);
// Display current GPU tuning states
void GetCurrentStates(IADLXManualGraphicsTuning1Ptr manualGFXTuning1);
void GetCurrentStates(IADLXManualGraphicsTuning2Ptr manualGFXTuning2);
// Set GPU states
void SetGPUStates(IADLXManualGraphicsTuning1Ptr manualGFXTuning1);
void SetGPUStates(IADLXManualGraphicsTuning2Ptr manualGFXTuning2);

int main()
{
    ADLX_RESULT  res = ADLX_FAIL ;

    // Initialize ADLX
    res = g_ADLXHelp.Initialize();

    if (ADLX_SUCCEEDED (res))
    {
        IADLXGPUTuningServicesPtr gpuTuningService;
        res = g_ADLXHelp.GetSystemServices()->GetGPUTuningServices(&gpuTuningService);
        if (ADLX_FAILED  (res))
        {
            // Destroy ADLX
            res = g_ADLXHelp.Terminate ();
            std::cout << "Destroy ADLX res: " << res << std::endl;
            return WaitAndExit ("\tGet GPU tuning services failed", 0);
        }
        IADLXGPUListPtr gpus;
        res = g_ADLXHelp.GetSystemServices()->GetGPUs(&gpus);
        if (ADLX_FAILED  (res))
        {
            // Destroy ADLX
            res = g_ADLXHelp.Terminate ();
            std::cout << "Destroy ADLX res: " << res << std::endl;
            return WaitAndExit ("\tGet GPU list failed", 0);
        }
        IADLXGPUPtr oneGPU;
        res = gpus->At(0, &oneGPU);
        if (ADLX_FAILED  (res) || oneGPU == nullptr)
        {
            // Destroy ADLX
            res = g_ADLXHelp.Terminate ();
            std::cout << "Destroy ADLX res: " << res << std::endl;
            return WaitAndExit ("\tGet GPU failed", 0);
        }
        adlx_bool supported = false;
        res = gpuTuningService->IsSupportedManualGFXTuning(oneGPU, &supported);
        if (ADLX_FAILED  (res) || supported == false)
        {
            // Destroy ADLX
            res = g_ADLXHelp.Terminate ();
            std::cout << "Destroy ADLX res: " << res << std::endl;
            return WaitAndExit ("\tThis GPU doesn't supported manual graphics tuning", 0);
        }
        IADLXInterfacePtr manualGFXTuningIfc;
        res = gpuTuningService->GetManualGFXTuning(oneGPU, &manualGFXTuningIfc);
        if (ADLX_FAILED  (res) || manualGFXTuningIfc == nullptr)
        {
            // Destroy ADLX
            res = g_ADLXHelp.Terminate ();
            std::cout << "Destroy ADLX res: " << res << std::endl;
            return WaitAndExit ("\tGet manual graphics tuning interface failed", 0);
        }
        // Pre-Navi ASIC
        IADLXManualGraphicsTuning1Ptr manualGFXTuning1(manualGFXTuningIfc);
        // Post-Navi ASIC
        IADLXManualGraphicsTuning2Ptr manualGFXTuning2(manualGFXTuningIfc);
        if (manualGFXTuning1 == nullptr && manualGFXTuning2 == nullptr)
        {
            // Destroy ADLX
            res = g_ADLXHelp.Terminate ();
            std::cout << "Destroy ADLX res: " << res << std::endl;
            return WaitAndExit ("\tGet manual graphics tuning failed", 0);
        }
        // Display main menu options
        MainMenu(manualGFXTuning1, manualGFXTuning2);

        // Get and execute the choice
        MenuControl(manualGFXTuning1, manualGFXTuning2);
    }
    else
        return WaitAndExit("\tg_ADLXHelp initialize failed", 0);

    // Destroy ADLX
    res = g_ADLXHelp.Terminate();
    std::cout << "Destroy ADLX res: " << res << std::endl;

    // Pause to see the print out
    system("pause");

    return 0;
}

// Main menu
void MainMenu(IADLXManualGraphicsTuning1Ptr manualGFXTuning1, IADLXManualGraphicsTuning2Ptr manualGFXTuning2)
{

    if (manualGFXTuning1)
        std::cout << "\tThe current GPU is pre-Navi. Choose from the following options:" << std::endl;
    else if (manualGFXTuning2)
        std::cout << "\tThe current GPU is post-Navi. Choose from the following options:" << std::endl;
    std::cout << "\t->Press 1 to display GPU frequency and voltage" << std::endl;
    std::cout << "\t->Press 2 to display current GPU states" << std::endl;
    std::cout << "\t->Press 3 to set GPU states" << std::endl;
    std::cout << "\t->Press Q/q to terminate the application" << std::endl;
    std::cout << "\t->Press M/m to display main menu options" << std::endl;
}

void MenuControl(IADLXManualGraphicsTuning1Ptr manualGFXTuning1, IADLXManualGraphicsTuning2Ptr manualGFXTuning2)
{
    char num = 0;
    while ((num = getchar()) != 'q' && num != 'Q')
    {
        //  Pre-Navi Menu action control
        if (manualGFXTuning1)
        {
            switch (num)
            {
            // Display GPU frequency and voltage range
            case '1':
                ShowFrequencyAndVoltageRange(manualGFXTuning1);
                break;

            // Display current GPU tuning states
            case '2':
                GetCurrentStates(manualGFXTuning1);
                break;

            // Set GPU states
            case '3':
                SetGPUStates(manualGFXTuning1);
                break;

            // Display menu options
            case 'm':
            case 'M':
                MainMenu(manualGFXTuning1, manualGFXTuning2);
                break;
            default:
                break;
            }
        }
        // Post-Navi Menu action control
        else
        {
            switch (num)
            {
            // Display GPU frequency and voltage range
            case '1':
                ShowFrequencyAndVoltageRange(manualGFXTuning2);
                break;

            // Display current GPU tuning states
            case '2':
                GetCurrentStates(manualGFXTuning2);
                break;

            // Set GPU states
            case '3':
                SetGPUStates(manualGFXTuning2);
                break;

            // Display menu options
            case 'm':
            case 'M':
                MainMenu(manualGFXTuning1, manualGFXTuning2);
                break;
            default:
                break;
            }
        }
    }
}

// Wait for exit with error message
int WaitAndExit(const char* msg, const int retCode)
{
    // Printout the message and pause to see it before returning the desired code
    if (nullptr != msg)
        std::cout << msg << std::endl;

    system("pause");
    return retCode;
}

// Display GPU frequency and voltage range
void ShowFrequencyAndVoltageRange(IADLXManualGraphicsTuning1Ptr manualGFXTuning1)
{
    ADLX_IntRange  freqRange, voltRange;
    ADLX_RESULT  res = manualGFXTuning1->GetGPUTuningRanges(&freqRange, &voltRange);
    std::cout << "\tFrequency range: (" << freqRange.minValue
              << ", " << freqRange.maxValue  << ")" << ", return code is: "<< res << "(0 means success)" << std::endl;
    std::cout << "\tVoltage range: (" << voltRange.minValue
              << ", " << voltRange.maxValue  << ")" << ", return code is: "<< res << "(0 means success)" << std::endl;
}

// Display current GPU tuning states
void GetCurrentStates(IADLXManualGraphicsTuning1Ptr manualGFXTuning1)
{
    IADLXManualTuningStateListPtr states;
    IADLXManualTuningStatePtr oneState;
    ADLX_RESULT  res = manualGFXTuning1->GetGPUTuningStates(&states);
    if (ADLX_SUCCEEDED  (res))
    {
        for (adlx_uint crt = states->Begin(); crt != states->End(); ++crt)
        {
            states->At(crt, &oneState);
            adlx_int freq = 0, volt = 0;
            res = oneState->GetFrequency(&freq);
            std::cout << "\tThe current state " << crt << ": frequency is " << freq << ", return code is: "<< res << "(0 means success)" << std::endl;
            res = oneState->GetVoltage(&volt);
            std::cout << "\tThe current state " << crt << ": voltage is " << volt << ", return code is: "<< res << "(0 means success)" << std::endl;
        }
    }
}

// Set GPU states
void SetGPUStates(IADLXManualGraphicsTuning1Ptr manualGFXTuning1)
{
    IADLXManualTuningStateListPtr states;
    IADLXManualTuningStatePtr oneState;
    ADLX_RESULT  res1 = manualGFXTuning1->GetEmptyGPUTuningStates(&states);
    ADLX_IntRange  freqRange, voltRange;
    ADLX_RESULT  res2 = manualGFXTuning1->GetGPUTuningRanges(&freqRange, &voltRange);
    if (ADLX_SUCCEEDED  (res1) && ADLX_SUCCEEDED  (res2))
    {
        for (adlx_uint crt = states->Begin(); crt != states->End(); ++crt)
        {
            states->At(crt, &oneState);
            adlx_int freq = 0, volt = 0;
            int freqStep = (freqRange.maxValue  - freqRange.minValue ) / (states->Size());
            // The Step should not be too large
            if (freqStep >= 60)
                freqStep = 60;
            int voltStep = (voltRange.maxValue  - voltRange.minValue ) / (states->Size());
            // The Step should not be too large
            if (voltStep >= 20)
                voltStep = 20;
            ADLX_RESULT  res = oneState->SetFrequency(freqRange.minValue  + freqStep * crt);
            res = oneState->GetFrequency(&freq);
            res = oneState->SetVoltage(voltRange.minValue  + voltStep * crt);
            res = oneState->GetVoltage(&volt);
            std::cout << "\tSet empty state " << crt << ": frequency is " << freq << ", voltage is " << volt << ", return code is: "<< res << "(0 means success)" << std::endl;
        }
    }

    adlx_int errorIndex;
    ADLX_RESULT  res = manualGFXTuning1->IsValidGPUTuningStates(states, &errorIndex);
    if (ADLX_SUCCEEDED (res))
    {
        res = manualGFXTuning1->SetGPUTuningStates(states);
        std::cout << "\tSet GPU tuning states " << (ADLX_SUCCEEDED  (res) ? "succeeded" : "failed") << std::endl;
    }
    else
        std::cout << "\tIsValidGPUTuningStates, errorIndex is : " << errorIndex << std::endl;

    res = manualGFXTuning1->GetGPUTuningStates(&states);
    std::cout << "\tAfter setting:" << std::endl;
    if (ADLX_SUCCEEDED  (res))
    {
        for (adlx_uint crt = states->Begin(); crt != states->End(); ++crt)
        {
            res = states->At(crt, &oneState);
            adlx_int freq = 0, volt = 0;
            res = oneState->GetFrequency(&freq);
            res = oneState->GetVoltage(&volt);
            std::cout << "\tThe current state " << crt << ": frequency is " << freq << ", voltage is " << volt << ", return code is: "<< res << "(0 means success)" << std::endl;
        }
    }
}

// Display GPU frequency and voltage range
void ShowFrequencyAndVoltageRange(IADLXManualGraphicsTuning2Ptr manualGFXTuning2)
{
    ADLX_IntRange  freqRange, voltRange;
    ADLX_RESULT  res = manualGFXTuning2->GetGPUMinFrequencyRange(&freqRange);
    std::cout << "\tGPU min frequency range: (" << freqRange.minValue
              << ", " << freqRange.maxValue  << ")" << ", return code is: "<< res << "(0 means success)" << std::endl;
    res = manualGFXTuning2->GetGPUMaxFrequencyRange(&freqRange);
    std::cout << "\tGPU max frequency range: (" << freqRange.minValue
              << ", " << freqRange.maxValue  << ")" << ", return code is: "<< res << "(0 means success)" << std::endl;
    res = manualGFXTuning2->GetGPUVoltageRange(&voltRange);
    std::cout << "\tVoltage range: (" << voltRange.minValue
              << ", " << voltRange.maxValue  << ")" << ", return code is: "<< res << "(0 means success)" << std::endl;
}

// Display current GPU tuning states
void GetCurrentStates(IADLXManualGraphicsTuning2Ptr manualGFXTuning2)
{
    adlx_int minFreq = 0, maxFreq = 0, volt = 0;
    ADLX_RESULT  res = manualGFXTuning2->GetGPUMinFrequency(&minFreq);
    std::cout << "\tCurrent GPU min frequency: " << minFreq << ", return code is: "<< res << "(0 means success)" << std::endl;
    res = manualGFXTuning2->GetGPUMaxFrequency(&maxFreq);
    std::cout << "\tCurrent GPU max frequency: " << maxFreq << ", return code is: "<< res << "(0 means success)" << std::endl;
    res = manualGFXTuning2->GetGPUVoltage(&volt);
    std::cout << "\tCurrent GPU clock voltage: " << volt << ", return code is: "<< res << "(0 means success)" << std::endl;
}

// Set GPU states
void SetGPUStates(IADLXManualGraphicsTuning2Ptr manualGFXTuning2)
{
    ADLX_IntRange  freqRange, voltRange;
    ADLX_RESULT  res = manualGFXTuning2->GetGPUMinFrequencyRange(&freqRange);
    res = manualGFXTuning2->GetGPUVoltageRange(&voltRange);
    res = manualGFXTuning2->SetGPUMinFrequency(freqRange.minValue );
    std::cout << "\tSet GPU min frequency " << (ADLX_SUCCEEDED  (res) ? "succeeded" : "failed") << std::endl;
    res = manualGFXTuning2->SetGPUMaxFrequency(freqRange.minValue  + 100);
    std::cout << "\tSet GPU max frequency " << (ADLX_SUCCEEDED  (res) ? "succeeded" : "failed") << std::endl;
    res = manualGFXTuning2->SetGPUVoltage(voltRange.minValue  + (voltRange.maxValue  - voltRange.minValue ) / 2);
    std::cout << "\tSet GPU voltage " << (ADLX_SUCCEEDED  (res) ? "succeeded" : "failed") << std::endl;
    std::cout << "\tAfter setting:" << std::endl;
    adlx_int minFreq = 0, maxFreq = 0, volt = 0;
    res = manualGFXTuning2->GetGPUMinFrequency(&minFreq);
    std::cout << "\tCurrent GPU min frequency: " << minFreq << ", return code is: "<< res << "(0 means success)" << std::endl;
    res = manualGFXTuning2->GetGPUMaxFrequency(&maxFreq);
    std::cout << "\tCurrent GPU max frequency: " << maxFreq << ", return code is: "<< res << "(0 means success)" << std::endl;
    res = manualGFXTuning2->GetGPUVoltage(&volt);
    std::cout << "\tCurrent GPU clock voltage: " << volt << ", return code is: "<< res << "(0 means success)" << std::endl;
}