Force using the dedicated GPU

Hi there fellow devs,

I tried for some time now to force my MonoGame-based app to use the dedicated graphics chip on a hybrid Intel/NVidia laptop. Unfortunately by default the integrated intel graphics card is used.

So I found the official hints from AMD and NVidia to use the following exports in C/C++ to make the driver recognize that the stronger GPU should be used:

extern "C" {
  _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}

and

extern "C" {
  _declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
}

I tried to set these using the UnmanagedCallersOnlyAttribute with no success so far.

Additionally I found hints here (nvidia) and here (amd) that statically linking or otherwise calling the respective API would cause the driver to switch to the dedicated GPU.

Is there any better way to do this as of MonoGame 3.8 / .NET 5?

Cheers,
Georg

PS: There’s a whole lot of solutions written down at SO and another often cited solution at LucasMagder. But neither of them seem to be very stable.
PPS: The other topic in the forum unfortunately did not list a solution for AMD devices.

Solutions for NVidia Optimus

Right at the start of the application call:

NativeLibrary.Load( "nvapi64.dll" );

Might help on AMD:

NativeLibrary.Load( "vulkan-1.dll" );

Another answer at the SE post suggests to fiddle with the IL code and add this:

.class public WindowsApplication1.ForceDedicatedGraphicCard
{
  .method public static int32 NvOptimusEnablement() cil managed
  {
    .export [1]
    ldc.i4.1
    ret
  }
  .method public static uint32 AmdPowerXpressRequestHighPerformance() cil managed
  {
    .export [2]
    ldc.i4.1
    ret
  }
}

I thought this might be similar to doing the following, which however did not seem to work:

[UnmanagedCallersOnly( CallConvs = new[] { typeof( CallConvCdecl ) } )]
public static int NvOptimusEnablement()
{
  return 1;
}

[UnmanagedCallersOnly( CallConvs = new[] { typeof( CallConvCdecl ) } )]
public static int AmdPowerXpressRequestHighPerformance()
{
  return 1;
}