ManualVRAMTuning

Demonstrates how to control GPU manual VRAM tuning when programming with ADLX.

Command Prompts

Command Prompt Description
1 Get Memory Timing support.
2 Get Memory Timing level and VRAMTuning state(Frequency and Voltage).Enable
3 Set Memory Timing level.
4 Set VRAMTuning state.
M/m Show this menu.
Q/q Quit.

Sample Path

/Samples/C/GPUTuning/ManualVRAMTuning

Code

Copied!

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


#include "SDK/ADLXHelper/Windows/C/ADLXHelper.h"
#include "SDK/Include/IGPUManualVRAMTuning.h"
#include "SDK/Include/IGPUTuning.h"

// Display Memory Timing support
void ShowSupport(IADLXInterface* vramTuni.gifc);

// Get VRAM state
void GetState(IADLXInterface* vramTuni.gifc);

// Set Memory Timing Level
void SetTimingLevel(IADLXInterface* vramTuni.gifc);

// Set VRAM state
void SetState(IADLXInterface* vramTuni.gifc);

// Main menu
void MainMenu(IADLXInterface* vramTuni.gifc);

// Menu action control
void MenuControl(IADLXInterface* vramTuni.gifc);

int main()
{
    // Define return code
    ADLX_RESULT  res = ADLX_FAIL ;

    // Initialize ADLX
    res = ADLXHelper_Initialize();

    if (ADLX_SUCCEEDED (res))
    {
        // Get System Services
        IADLXSystem* sys = ADLXHelper_GetSystemServices();

        // Get GPUs
        IADLXGPUList* gpus = NULL;
        res = sys->pVtbl->GetGPUs(sys, &gpus);

        // Get GPU tuning service
        IADLXGPUTuningServices* gpuTuningService = NULL;
        res = sys->pVtbl->GetGPUTuningServices(sys, &gpuTuningService);

        if (ADLX_SUCCEEDED (res))
        {
                // Get GPU interface
            IADLXGPU* gpu = NULL;
            adlx_uint index = 0;
            res = gpus->pVtbl->At_GPUList(gpus, index, &gpu);

                    // Get ManualVRAMTuning support
            adlx_bool supported;
            gpuTuningService->pVtbl->IsSupportedManualVRAMTuning(gpuTuningService, gpu, &supported);
            printf("\\tThe GPU support for manual VRAM tuning is: %d \\n", supported);

            if (supported)
            {
                // Get ManualVRAMTuning interface
                IADLXInterface* vramTuni.gifc = NULL;
                res = gpuTuningService->pVtbl->GetManualVRAMTuning(gpuTuningService, gpu, &vramTuni.gifc);
                if (ADLX_SUCCEEDED (res))
                {
                    MainMenu(vramTuni.gifc);
                    MenuControl(vramTuni.gifc);
                }
                // Release the vramTuni.gifc interface
                if (vramTuni.gifc != NULL)
                {
                    vramTuni.gifc->pVtbl->Release(vramTuni.gifc);
                    vramTuni.gifc = NULL;
                }
            }
            else
            {
                printf("\\tThis GPU Doesn't support Manual VRAM Tuning \\n");
            }


            // Release the GPU interface
            if (gpu != NULL)
            {
                gpu->pVtbl->Release(gpu);
                gpu = NULL;
            }
        }
        else
        {
            printf("Failed to get GPU tuning service\\n");
        }

        // Release the gpuTuningService interface
        if (gpuTuningService != NULL)
        {
            gpuTuningService->pVtbl->Release(gpuTuningService);
            gpuTuningService = NULL;
        }

        // Release the GPUs list interface
        if (gpus != NULL)
        {
            gpus->pVtbl->Release(gpus);
            gpus = NULL;
        }
    }
    else
    {
        printf("ADLX initialization failed\\n");
        return 0;
    }

    // Destroy ADLX
    res = ADLXHelper_Terminate();
    printf("Destroy ADLX res: %d\\n", res);

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

    return 0;
}

static const char* getDescStr(ADLX_MEMORYTIMING_DESCRIPTION  desc)
{
    switch (desc)
    {
    case MEMORYTIMING_DEFAULT :
        return "Default";
    case MEMORYTIMING_FAST_TIMING :
        return "Fast Timing";
    case MEMORYTIMING_FAST_TIMING_LEVEL_2 :
        return "Fast Timing Level2";
    case MEMORYTIMING_AUTOMATIC :
        return "Automatic";
    case MEMORYTIMING_MEMORYTIMING_LEVEL_1 :
        return "Memory Timing Level1";
    case MEMORYTIMING_MEMORYTIMING_LEVEL_2 :
        return "Memory Timing Level2";
    }
    return "Default";
};

void ShowSupport(IADLXInterface* vramTuni.gifc)
{
    adlx_bool supported = false;
    IADLXManualVRAMTuning2* vramTuning2 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning2(), &vramTuning2);
    IADLXManualVRAMTuning1* vramTuning1 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning1(), &vramTuning1);
    ADLX_RESULT  res = ADLX_FAIL ;
    if (vramTuning2)
    {
        res = vramTuning2->pVtbl->IsSupportedMemoryTiming(vramTuning2, &supported);
    }
    else if (vramTuning1)
    {
        res = vramTuning1->pVtbl->IsSupportedMemoryTiming(vramTuning1, &supported);
    }

    printf("\\tIsSupported: %d, return code is: %d(0 means success)\\n", supported, res);

    // Release the ManualVRAMTuning2 interface
    if (vramTuning2 != NULL)
    {
        vramTuning2->pVtbl->Release(vramTuning2);
        vramTuning2 = NULL;
    }

    // Release the ManualVRAMTuning1 interface
    if (vramTuning1 != NULL)
    {
        vramTuning1->pVtbl->Release(vramTuning1);
        vramTuning1 = NULL;
    }
}

void GetState(IADLXInterface* vramTuni.gifc)
{
    IADLXManualVRAMTuning2* vramTuning2 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning2(), &vramTuning2);
    IADLXManualVRAMTuning1* vramTuning1 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning1(), &vramTuning1);
    ADLX_MEMORYTIMING_DESCRIPTION  desc;
    IADLXMemoryTimingDescriptionList* descList = NULL;
    if (vramTuning2)
    {
        vramTuning2->pVtbl->GetSupportedMemoryTimingDescriptionList(vramTuning2, &descList);
        vramTuning2->pVtbl->GetMemoryTimingDescription(vramTuning2, &desc);

        adlx_int freq;
        ADLX_IntRange  rang;
        ADLX_RESULT  res = vramTuning2->pVtbl->GetMaxVRAMFrequency(vramTuning2, &freq);
        printf("\\tMaxVRAMFrequency is: %d, return code is: %d(0 means success)\\n", freq, res);
        res = vramTuning2->pVtbl->GetMaxVRAMFrequencyRange(vramTuning2, &rang);
        printf("\\tMaxVRAMFrequencyRange: [ %d, %d ], step: %d, return code is: %d(0 means success)\\n", rang.minValue , rang.maxValue , rang.step , res);

        IADLXManualVRAMTuning2_1* vramTuning2_1;
        vramTuning2->pVtbl->QueryInterface(vramTuning2, IID_IADLXManualVRAMTuning2_1(), (void**)&vramTuning2_1);
        if (vramTuning2_1)
        {
            res = vramTuning2_1->pVtbl->GetMaxVRAMFrequencyDefault(vramTuning2_1, &freq);
            printf("\\tDefault MaxVRAMFrequency is: %d, return code is: %d(0 means success)\\n", freq, res);
            // release vramTuning2_1
            vramTuning2_1->pVtbl->Release(vramTuning2_1);
            vramTuning2_1 = NULL;
        }
    }
    else if (vramTuning1)
    {
        vramTuning1->pVtbl->GetSupportedMemoryTimingDescriptionList(vramTuning1, &descList);
        vramTuning1->pVtbl->GetMemoryTimingDescription(vramTuning1, &desc);

        IADLXManualTuningStateList* states = NULL;
        vramTuning1->pVtbl->GetVRAMTuningStates(vramTuning1, &states);
        adlx_uint s = states->pVtbl->Begin(states);
        printf("\\tState is:\\n");
        for (; s != states->pVtbl->End(states); s++)
        {
            IADLXManualTuningState* state = NULL;
            adlx_int frequency;
            adlx_int voltage;
            states->pVtbl->At_ManualTuningStateList(states, s, &state);
            state->pVtbl->GetFrequency(state, &frequency);
            state->pVtbl->GetVoltage(state, &voltage);
            printf("\\t\\tfrequency: %d, voltage: %d \\n", frequency, voltage);
            if (state != NULL)
            {
                state->pVtbl->Release(state);
                state = NULL;
            }
        }
        if (states != NULL)
        {
            states->pVtbl->Release(states);
            states = NULL;
        }

        ADLX_IntRange  frequencyRange;
        ADLX_IntRange  voltageRange;
        ADLX_RESULT  res = vramTuning1->pVtbl->GetVRAMTuningRanges(vramTuning1, &frequencyRange, &voltageRange);
        printf("\\tFrequency Range: [ %d, %d ], step: %d, return code is: %d(0 means success)\\n", frequencyRange.minValue , frequencyRange.maxValue , frequencyRange.step , res);
        printf("\\tVoltage Range: [ %d, %d ], step: %d, return code is: %d(0 means success)\\n", voltageRange.minValue , voltageRange.maxValue , voltageRange.step , res);
    }

    if (descList)
    {
        printf ("\\tCurrent Timing desc is: %s\\n", getDescStr (desc));
        printf ("\\tSupported memory timing desc list:\\n");
        for (adlx_uint s = 0; s != descList->pVtbl->End (descList); s++)
        {
            IADLXMemoryTimingDescription* item = NULL;
            descList->pVtbl->At_MemoryTimingDescriptionList (descList, s, &item);
            item->pVtbl->GetDescription (item, &desc);
            printf ("\\t  %s\\n", getDescStr (desc));

            // Release the IADLXMemoryTimingDescription interface
            if (item)
            {
                item->pVtbl->Release (item);
                item = NULL;
            }
        }
    }
    printf("\\n");

    // Release the IADLXMemoryTimingDescriptionList interface
    if (descList != NULL)
    {
        descList->pVtbl->Release(descList);
        descList = NULL;
    }

    // Release the ManualVRAMTuning2 interface
    if (vramTuning2 != NULL)
    {
        vramTuning2->pVtbl->Release(vramTuning2);
        vramTuning2 = NULL;
    }

    // Release the ManualVRAMTuning1 interface
    if (vramTuning1 != NULL)
    {
        vramTuning1->pVtbl->Release(vramTuning1);
        vramTuning1 = NULL;
    }
}

void SetTimingLevel(IADLXInterface* vramTuni.gifc)
{
    ADLX_RESULT  res;
    IADLXManualVRAMTuning2* vramTuning2 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning2(), &vramTuning2);
    IADLXManualVRAMTuning1* vramTuning1 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning1(), &vramTuning1);
    ADLX_MEMORYTIMING_DESCRIPTION  desc, currentDesc;
    IADLXMemoryTimingDescriptionList* descList = NULL;
    IADLXMemoryTimingDescription* item = NULL;
    adlx_bool supported = false;
    if (vramTuning2)
    {
        //If MemoryTiming is supported, then only will set the MemoryTiming
        res = vramTuning2->pVtbl->IsSupportedMemoryTiming(vramTuning2, &supported);
        if (supported)
        {
            res = vramTuning2->pVtbl->GetSupportedMemoryTimingDescriptionList(vramTuning2, &descList);
            if (descList)
            {
                vramTuning2->pVtbl->GetMemoryTimingDescription(vramTuning2, &currentDesc);
                for (adlx_uint s = 0; s != descList->pVtbl->End(descList); s++)
                {
                    descList->pVtbl->At_MemoryTimingDescriptionList(descList, s, &item);
                    item->pVtbl->GetDescription(item, &desc);
                    if (desc != currentDesc)
                    {
                        res = vramTuning2->pVtbl->SetMemoryTimingDescription(vramTuning2, desc);
                        printf("\\tSet Memory Timing description to %s: return code is: %d (0 means success)\\n", getDescStr(desc), res);
                        break;
                    }
                }
            }
            else
            {
                printf("\\tFailed to get the Supported Memory Timing Description List.\\n");
            }
        }
        else
        {

            printf("\\tMemory Timing level not supported, so cannot set Memory Timing Description List\\n");
        }
    }
    else if (vramTuning1)
    {
        //If MemoryTiming is supported, then only will set the MemoryTiming
        res = vramTuning1->pVtbl->IsSupportedMemoryTiming(vramTuning1, &supported);
        if (supported)
        {
            res = vramTuning1->pVtbl->GetSupportedMemoryTimingDescriptionList(vramTuning1, &descList);
            if (descList)
            {
                vramTuning1->pVtbl->GetMemoryTimingDescription(vramTuning1, &currentDesc);
                for (adlx_uint s = 0; s != descList->pVtbl->End(descList); s++)
                {
                    descList->pVtbl->At_MemoryTimingDescriptionList(descList, s, &item);
                    item->pVtbl->GetDescription(item, &desc);
                    if (desc != currentDesc)
                    {
                        res = vramTuning1->pVtbl->SetMemoryTimingDescription(vramTuning1, desc);
                        printf("\\tSet Memory Timing description to %s: return code is: %d (0 means success)\\n", getDescStr(desc), res);
                        break;
                    }
                }
            }
            else
            {
                printf("\\tFailed to get the Supported Memory Timing Description List.\\n");
            }
        }
        else
        {
            printf("\\tMemory Timing level not supported, so cannot set Memory Timing Description List\\n");
        }
    }

    // Release the IADLXMemoryTimingDescription interface
    if (item != NULL)
    {
        item->pVtbl->Release(item);
        item = NULL;
    }

    // Release the IADLXMemoryTimingDescriptionList interface
    if (descList != NULL)
    {
        descList->pVtbl->Release(descList);
        descList = NULL;
    }

    // Release the ManualVRAMTuning2 interface
    if (vramTuning2 != NULL)
    {
        vramTuning2->pVtbl->Release(vramTuning2);
        vramTuning2 = NULL;
    }

    // Release the ManualVRAMTuning1 interface
    if (vramTuning1 != NULL)
    {
        vramTuning1->pVtbl->Release(vramTuning1);
        vramTuning1 = NULL;
    }
}

void SetState(IADLXInterface* vramTuni.gifc)
{
    ADLX_RESULT  res;
    IADLXManualVRAMTuning2* vramTuning2 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning2(), &vramTuning2);
    IADLXManualVRAMTuning1* vramTuning1 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning1(), &vramTuning1);
    adlx_bool supported = false;
    if (vramTuning2)
    {
        //If MemoryTiming is supported, then only will set the state
        res = vramTuning2->pVtbl->IsSupportedMemoryTiming(vramTuning2, &supported);
        if (supported)
        {
            adlx_int freq;
            ADLX_IntRange  rang;
            vramTuning2->pVtbl->GetMaxVRAMFrequency(vramTuning2, &freq);
            vramTuning2->pVtbl->GetMaxVRAMFrequencyRange(vramTuning2, &rang);
            if (freq != rang.minValue )
            {
                res = vramTuning2->pVtbl->SetMaxVRAMFrequency(vramTuning2, rang.minValue );
                printf("\\tSet minimum frequency: return code is: %d (0 means success)\\n", res);
            }
            else
            {
                res = vramTuning2->pVtbl->SetMaxVRAMFrequency(vramTuning2, rang.minValue  + rang.step  * 2);
                printf("\\tSet maximum frequency: return code is: %d (0 means success)\\n", res);
            }
        }
        else
        {
            printf("\\tTuning not supported, cannot set the state\\n");
        }
    }
    else if (vramTuning1)
    {
        //If MemoryTiming is supported, then only will set the state
        res = vramTuning1->pVtbl->IsSupportedMemoryTiming(vramTuning1, &supported);
        if (supported)
        {
            ADLX_IntRange  frequencyRange;
            ADLX_IntRange  voltageRange;
            vramTuning1->pVtbl->GetVRAMTuningRanges(vramTuning1, &frequencyRange, &voltageRange);
            IADLXManualTuningStateList* states = NULL;
            vramTuning1->pVtbl->GetVRAMTuningStates(vramTuning1, &states);
            adlx_uint s = states->pVtbl->Begin(states);
            for (; s != states->pVtbl->End(states); s++)
            {
                IADLXManualTuningState* state = NULL;
                adlx_int frequency;
                adlx_int voltage;
                states->pVtbl->At_ManualTuningStateList(states, s, &state);
                state->pVtbl->GetFrequency(state, &frequency);
                state->pVtbl->GetVoltage(state, &voltage);
                // Only change the first
                res = state->pVtbl->SetFrequency(state, frequency != frequencyRange.minValue  ? frequencyRange.minValue  : frequencyRange.maxValue );
                res = state->pVtbl->SetVoltage(state, voltage != voltageRange.minValue  ? voltageRange.minValue  : voltageRange.maxValue );
                break;
            }
            res = vramTuning1->pVtbl->SetVRAMTuningStates(vramTuning1, states);
            printf("\\tChange VRAM tuning states: return code is: %d (0 means success)\\n", res);
        }
        else
        {
            printf("\\tTuning not supported, cannot set the state\\n");
        }
    }

    // Release the ManualVRAMTuning2 interface
    if (vramTuning2 != NULL)
    {
        vramTuning2->pVtbl->Release(vramTuning2);
        vramTuning2 = NULL;
    }

    // Release the ManualVRAMTuning1 interface
    if (vramTuning1 != NULL)
    {
        vramTuning1->pVtbl->Release(vramTuning1);
        vramTuning1 = NULL;
    }
}

void MainMenu(IADLXInterface* vramTuni.gifc)
{
    IADLXManualVRAMTuning2* vramTuning2 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning2(), &vramTuning2);
    IADLXManualVRAMTuning1* vramTuning1 = NULL;
    vramTuni.gifc->pVtbl->QueryInterface(vramTuni.gifc, IID_IADLXManualVRAMTuning1(), &vramTuning1);
    printf("\\tChoose from the following options:\\n");

    printf("\\t->Press 1 to display Memory Timing support\\n");
    if (vramTuning2)
        printf("\\t->Press 2 to display Memory Timing level and frequency range\\n");
    else if (vramTuning1)
        printf("\\t->Press 2 to display Memory Timing level, VRAM frequency, and the voltage global range for all states\\n");

    printf("\\t->Press 3 to change current Memory Timing Level\\n");
    if (vramTuning2)
        printf("\\t->Press 4 to change current VRAM maximum frequency value\\n");
    else if (vramTuning1)
        printf("\\t->Press 4 to change VRAM states\\n");

    printf("\\t->Press Q/q to terminate the application\\n");
    printf("\\t->Press M/m to display main menu options\\n");

    // Release the ManualVRAMTuning2 interface
    if (vramTuning2 != NULL)
    {
        vramTuning2->pVtbl->Release(vramTuning2);
        vramTuning2 = NULL;
    }

    // Release the ManualVRAMTuning1 interface
    if (vramTuning1 != NULL)
    {
        vramTuning1->pVtbl->Release(vramTuning1);
        vramTuning1 = NULL;
    }
}

void MenuControl(IADLXInterface* vramTuni.gifc)
{
    int num = 0;
    while ((num = getchar()) != 'q' && num != 'Q')
    {
        switch (num)
        {
        // Get Memory Timing support
        case '1':
            ShowSupport(vramTuni.gifc);
            break;

        // Get VRAM state
        case '2':
            GetState(vramTuni.gifc);
            break;

        // Set timing level
        case '3':
            SetTimingLevel(vramTuni.gifc);
            break;

        // Set VRAM state
        case '4':
            SetState(vramTuni.gifc);
            break;

        // Display menu options
        case 'm':
        case 'M':
            MainMenu(vramTuni.gifc);
            break;
        default:
            break;
        }
    }
}

Related pages

  • Visit the Adlx product page for download links and more information.

Looking for more documentation on GPUOpen?

AMD GPUOpen software blogs

Our handy software release blogs will help you make good use of our tools, SDKs, and effects, as well as sharing the latest features with new releases.

GPUOpen Manuals

Don’t miss our manual documentation! And if slide decks are what you’re after, you’ll find 100+ of our finest presentations here.

AMD GPUOpen Performance Guides

The home of great performance and optimization advice for AMD RDNA™ 2 GPUs, AMD Ryzen™ CPUs, and so much more.

Getting started: AMD GPUOpen software

New or fairly new to AMD’s tools, libraries, and effects? This is the best place to get started on GPUOpen!

AMD GPUOpen Getting Started Development and Performance

Looking for tips on getting started with developing and/or optimizing your game, whether on AMD hardware or generally? We’ve got you covered!

AMD GPUOpen Technical blogs

Browse our technical blogs, and find valuable advice on developing with AMD hardware, ray tracing, Vulkan®, DirectX®, Unreal Engine, and lots more.

Find out more about our software!

AMD GPUOpen Effects - AMD FidelityFX technologies

Create wonder. No black boxes. Meet the AMD FidelityFX SDK!

AMD GPUOpen Samples

Browse all our useful samples. Perfect for when you’re needing to get started, want to integrate one of our libraries, and much more.

AMD GPUOpen developer SDKs

Discover what our SDK technologies can offer you. Query hardware or software, manage memory, create rendering applications or machine learning, and much more!

AMD GPUOpen Developer Tools

Analyze, Optimize, Profile, Benchmark. We provide you with the developer tools you need to make sure your game is the best it can be!