Skip to content

Instantly share code, notes, and snippets.

@parzivail
Created July 27, 2025 16:15
Show Gist options
  • Save parzivail/e97ef414661b1168359254a4fbf9ccbb to your computer and use it in GitHub Desktop.
Save parzivail/e97ef414661b1168359254a4fbf9ccbb to your computer and use it in GitHub Desktop.
Creates a profile in the NVIDIA Control Panel that disables Threaded Optimization
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
namespace NvidiaInterop_cs;
internal static class NvidiaInterop
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private unsafe struct NvAPI_UnicodeString
{
private fixed byte _data[4096];
public NvAPI_UnicodeString(string text)
{
Set(text);
}
public void Set(string text)
{
text += '\0';
fixed (char* textPtr = text)
fixed (byte* data = _data)
{
Encoding.Unicode.GetBytes(textPtr, text.Length, data, 4096);
}
}
}
[Flags]
private enum NVDRS_APPLICATION_V4_FLAGS : uint
{
Metro = 0b01,
CommandLine = 0b10
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct NVDRS_APPLICATION_V4
{
public uint Version;
public NvBool32 IsPredefined;
public NvAPI_UnicodeString AppName;
public NvAPI_UnicodeString UserFriendlyName;
public NvAPI_UnicodeString Launcher;
public NvAPI_UnicodeString FileInFolder;
public NVDRS_APPLICATION_V4_FLAGS Flags;
public NvAPI_UnicodeString CommandLine;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct NVDRS_PROFILE
{
public uint Version;
public NvAPI_UnicodeString ProfileName;
public uint GpuSupport;
public NvBool32 IsPredefined;
public uint NumOfApps;
public uint NumOfSettings;
}
private enum NVDRS_SETTING_TYPE : uint
{
NVDRS_DWORD_TYPE = 0x00000000
}
private enum NVDRS_SETTING_LOCATION : uint
{
NvdrsCurrentProfileLocation = 0x00000000
}
private enum NvBool32 : uint
{
False = 0x00000000,
True = 0x00000001
}
[StructLayout(LayoutKind.Explicit, Size = 0x3020)]
private struct NVDRS_SETTING
{
[FieldOffset(0x0)]
public uint Version;
[FieldOffset(0x4)]
public NvAPI_UnicodeString SettingName;
[FieldOffset(0x1004)]
public NvAPIConstants SettingId;
[FieldOffset(0x1008)]
public NVDRS_SETTING_TYPE SettingType;
[FieldOffset(0x100C)]
public NVDRS_SETTING_LOCATION SettingLocation;
[FieldOffset(0x1010)]
public NvBool32 IsCurrentPredefined;
[FieldOffset(0x1014)]
public NvBool32 IsPredefinedValid;
[FieldOffset(0x1018)]
public uint PredefinedValue;
[FieldOffset(0x201C)]
public uint CurrentValue;
}
private enum NvAPI_Status : uint
{
NVAPI_OK = 0x00000000
}
private enum NvAPIConstants : uint
{
SHIM_MCCOMPAT_ID = 0x10F9DC80,
SHIM_MCCOMPAT_ENABLE = 0x00000001,
SHIM_RENDERING_MODE_ID = 0x10F9DC81,
SHIM_RENDERING_MODE_ENABLE = 0x00000001,
SHIM_RENDERING_OPTIONS_ID = 0x10F9DC84,
SHIM_RENDERING_OPTIONS_DEFAULT_RENDERING_MODE = 0x00000000,
OGL_THREAD_CONTROL_ID = 0x20C1221E,
OGL_THREAD_CONTROL_DISABLE = 0x00000002
}
private enum NvAPIMethods : uint
{
NvAPI_Initialize_ID = 0x0150E828,
NvAPI_DRS_CreateSession_ID = 0x0694D52E,
NvAPI_DRS_LoadSettings_ID = 0x375DBD6B,
NvAPI_DRS_FindProfileByName_ID = 0x7E4A9A0B,
NvAPI_DRS_CreateProfile_ID = 0x0CC176068,
NvAPI_DRS_CreateApplication_ID = 0x4347A9DE,
NvAPI_DRS_SetSetting_ID = 0x577DD202,
NvAPI_DRS_SaveSettings_ID = 0xFCBC7E14,
NvAPI_DRS_DestroySession_ID = 0x0DAD9CFF8
}
private const string LibraryPath = "nvapi64.dll";
[DllImport(LibraryPath)]
private static extern IntPtr nvapi_QueryInterface(NvAPIMethods id);
private static unsafe delegate*<NvAPI_Status> NvAPI_Initialize;
private static unsafe delegate*<out IntPtr, NvAPI_Status> NvAPI_DRS_CreateSession;
private static unsafe delegate*<IntPtr, NvAPI_Status> NvAPI_DRS_LoadSettings;
private static unsafe delegate*<IntPtr, NvAPI_UnicodeString, out IntPtr, NvAPI_Status> NvAPI_DRS_FindProfileByName;
private static unsafe delegate*<IntPtr, ref NVDRS_PROFILE, ref IntPtr, NvAPI_Status> NvAPI_DRS_CreateProfile;
private static unsafe delegate*<IntPtr, IntPtr, ref NVDRS_APPLICATION_V4, NvAPI_Status> NvAPI_DRS_CreateApplication;
private static unsafe delegate*<IntPtr, IntPtr, ref NVDRS_SETTING, NvAPI_Status> NvAPI_DRS_SetSetting;
private static unsafe delegate*<IntPtr, NvAPI_Status> NvAPI_DRS_SaveSettings;
private static unsafe delegate*<IntPtr, NvAPI_Status> NvAPI_DRS_DestroySession;
private static void AssertSuccess(string method, NvAPI_Status status)
{
if (status == NvAPI_Status.NVAPI_OK)
return;
throw new Exception($"NvAPI failure: {method} returned {status}");
}
private static uint MAKE_NVAPI_VERSION<T>(uint version) where T : unmanaged
{
return (uint)Unsafe.SizeOf<T>() | (version << 16);
}
public static unsafe bool Load(string profileName, string executableName, string friendlyName)
{
// A C# port of: https://stackoverflow.com/questions/36959508/nvidia-graphics-driver-causing-noticeable-frame-stuttering
// Attempt to locate the API. If we can't find it, we probably don't have an NVIDIA GPU.
if (!TryLoadApi())
return false;
// Attempt to initialize the API. If we can't, we have the drivers for an NVIDIA GPU, but no hardware.
NvAPI_Initialize = (delegate*<NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_Initialize_ID);
if (NvAPI_Initialize() != NvAPI_Status.NVAPI_OK)
return false;
// After we initialize the API, all other calls become assertions for NvAPI_Status.NVAPI_OK
// since the only call we will let fail is the initialization.
// If the initialization went well, continue on to find the rest of the handles
NvAPI_DRS_CreateSession = (delegate*<out IntPtr, NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_DRS_CreateSession_ID);
NvAPI_DRS_LoadSettings = (delegate*<IntPtr, NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_DRS_LoadSettings_ID);
NvAPI_DRS_FindProfileByName = (delegate*<IntPtr, NvAPI_UnicodeString, out IntPtr, NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_DRS_FindProfileByName_ID);
NvAPI_DRS_CreateProfile = (delegate*<IntPtr, ref NVDRS_PROFILE, ref IntPtr, NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_DRS_CreateProfile_ID);
NvAPI_DRS_CreateApplication = (delegate*<IntPtr, IntPtr, ref NVDRS_APPLICATION_V4, NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_DRS_CreateApplication_ID);
NvAPI_DRS_SetSetting = (delegate*<IntPtr, IntPtr, ref NVDRS_SETTING, NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_DRS_SetSetting_ID);
NvAPI_DRS_SaveSettings = (delegate*<IntPtr, NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_DRS_SaveSettings_ID);
NvAPI_DRS_DestroySession = (delegate*<IntPtr, NvAPI_Status>)GetMethodPointer(NvAPIMethods.NvAPI_DRS_DestroySession_ID);
// Get the session settings
AssertSuccess(nameof(NvAPI_DRS_CreateSession), NvAPI_DRS_CreateSession(out var session));
AssertSuccess(nameof(NvAPI_DRS_LoadSettings), NvAPI_DRS_LoadSettings(session));
// If the requested profile doesn't exist, create one
if (NvAPI_DRS_FindProfileByName(session, new NvAPI_UnicodeString(profileName), out var profile) != 0)
{
// Create a profile. This can be found in the NVIDIA Control Panel under the given name.
var profileValue = new NVDRS_PROFILE
{
Version = MAKE_NVAPI_VERSION<NVDRS_PROFILE>(1),
IsPredefined = NvBool32.False,
GpuSupport = uint.MaxValue,
ProfileName = new NvAPI_UnicodeString(profileName)
};
AssertSuccess(nameof(NvAPI_DRS_CreateProfile), NvAPI_DRS_CreateProfile(session, ref profileValue, ref profile));
// Create an application and assign it to that profile. The NVIDIA Control Panel will show
// this line item as:
// Profile Name (Friendly Executable Name)
// and it will only apply to the executable with the specified name.
var application = new NVDRS_APPLICATION_V4
{
Version = MAKE_NVAPI_VERSION<NVDRS_APPLICATION_V4>(4),
IsPredefined = NvBool32.False,
AppName = new NvAPI_UnicodeString(executableName),
UserFriendlyName = new NvAPI_UnicodeString(friendlyName),
Flags = NVDRS_APPLICATION_V4_FLAGS.Metro | NVDRS_APPLICATION_V4_FLAGS.CommandLine
};
AssertSuccess(nameof(NvAPI_DRS_CreateApplication), NvAPI_DRS_CreateApplication(session, profile, ref application));
}
// Apply our profile settings
// Disable Threaded Optimization
UpdateProfileSetting(
session,
profile,
NvAPIConstants.OGL_THREAD_CONTROL_ID,
NVDRS_SETTING_TYPE.NVDRS_DWORD_TYPE,
NvAPIConstants.OGL_THREAD_CONTROL_DISABLE
);
// Force the application to use the dedicated GPU, otherwise the previous settings do not apply.
UpdateProfileSetting(
session,
profile,
NvAPIConstants.SHIM_MCCOMPAT_ID,
NVDRS_SETTING_TYPE.NVDRS_DWORD_TYPE,
NvAPIConstants.SHIM_MCCOMPAT_ENABLE
);
UpdateProfileSetting(
session,
profile,
NvAPIConstants.SHIM_RENDERING_MODE_ID,
NVDRS_SETTING_TYPE.NVDRS_DWORD_TYPE,
NvAPIConstants.SHIM_RENDERING_MODE_ENABLE
);
UpdateProfileSetting(
session,
profile,
NvAPIConstants.SHIM_RENDERING_OPTIONS_ID,
NVDRS_SETTING_TYPE.NVDRS_DWORD_TYPE,
NvAPIConstants.SHIM_RENDERING_OPTIONS_DEFAULT_RENDERING_MODE
);
AssertSuccess(nameof(NvAPI_DRS_SaveSettings), NvAPI_DRS_SaveSettings(session));
NvAPI_DRS_DestroySession(session);
return true;
}
private static unsafe void UpdateProfileSetting(IntPtr handle, IntPtr profileHandle, NvAPIConstants settingId, NVDRS_SETTING_TYPE settingType, NvAPIConstants targetValue)
{
var setting = new NVDRS_SETTING
{
Version = MAKE_NVAPI_VERSION<NVDRS_SETTING>(1),
SettingId = settingId,
SettingType = settingType,
SettingLocation = NVDRS_SETTING_LOCATION.NvdrsCurrentProfileLocation,
IsCurrentPredefined = NvBool32.False,
IsPredefinedValid = NvBool32.False,
CurrentValue = (uint)targetValue,
PredefinedValue = (uint)targetValue
};
AssertSuccess(nameof(NvAPI_DRS_SetSetting), NvAPI_DRS_SetSetting(handle, profileHandle, ref setting));
}
private static IntPtr GetMethodPointer(NvAPIMethods method)
{
var ptr = nvapi_QueryInterface(method);
if (ptr == IntPtr.Zero)
throw new InvalidOperationException($"Failed to locate NvAPI method handle: {method}");
return ptr;
}
/// <summary>
/// Determine if the NVIDIA API is available. If it is, we probably
/// have a dedicated GPU at our disposal.
/// </summary>
public static bool TryLoadApi()
{
return NativeLibrary.TryLoad(LibraryPath, out _);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment