mirror of
https://github.com/jkocon/g-helper.git
synced 2026-02-23 13:00:52 +01:00
242 lines
6.9 KiB
C#
242 lines
6.9 KiB
C#
using GHelper.Helpers;
|
|
using NvAPIWrapper.GPU;
|
|
using NvAPIWrapper.Native;
|
|
using NvAPIWrapper.Native.GPU;
|
|
using NvAPIWrapper.Native.GPU.Structures;
|
|
using NvAPIWrapper.Native.Interfaces.GPU;
|
|
using System.Diagnostics;
|
|
using static NvAPIWrapper.Native.GPU.Structures.PerformanceStates20InfoV1;
|
|
|
|
namespace GHelper.Gpu.NVidia;
|
|
|
|
public class NvidiaGpuControl : IGpuControl
|
|
{
|
|
|
|
public static int MaxCoreOffset => AppConfig.Get("max_gpu_core", 250);
|
|
public static int MaxMemoryOffset => AppConfig.Get("max_gpu_memory", 250);
|
|
|
|
public static int MinCoreOffset = AppConfig.Get("min_gpu_core", -250);
|
|
public static int MinMemoryOffset = AppConfig.Get("min_gpu_memory", -250);
|
|
|
|
public const int MinClockLimit = 400;
|
|
public const int MaxClockLimit = 3000;
|
|
|
|
private static PhysicalGPU? _internalGpu;
|
|
|
|
public NvidiaGpuControl()
|
|
{
|
|
_internalGpu = GetInternalDiscreteGpu();
|
|
}
|
|
|
|
public bool IsValid => _internalGpu != null;
|
|
|
|
public bool IsNvidia => IsValid;
|
|
|
|
public string FullName => _internalGpu!.FullName;
|
|
|
|
public int? GetCurrentTemperature()
|
|
{
|
|
if (!IsValid) return null;
|
|
|
|
PhysicalGPU internalGpu = _internalGpu!;
|
|
IThermalSensor? gpuSensor =
|
|
GPUApi.GetThermalSettings(internalGpu.Handle).Sensors
|
|
.FirstOrDefault(s => s.Target == ThermalSettingsTarget.GPU);
|
|
|
|
return gpuSensor?.CurrentTemperature;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
public void KillGPUApps()
|
|
{
|
|
|
|
if (!IsValid) return;
|
|
PhysicalGPU internalGpu = _internalGpu!;
|
|
|
|
try
|
|
{
|
|
Process[] processes = internalGpu.GetActiveApplications();
|
|
foreach (Process process in processes)
|
|
try
|
|
{
|
|
Logger.WriteLine("Kill:" + process.ProcessName);
|
|
ProcessHelper.KillByProcess(process);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.WriteLine(ex.Message);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.WriteLine(ex.Message);
|
|
}
|
|
|
|
//GeneralApi.RestartDisplayDriver();
|
|
}
|
|
|
|
|
|
public bool GetClocks(out int core, out int memory)
|
|
{
|
|
PhysicalGPU internalGpu = _internalGpu!;
|
|
|
|
//Logger.WriteLine(internalGpu.FullName);
|
|
//Logger.WriteLine(internalGpu.ArchitectInformation.ToString());
|
|
|
|
try
|
|
{
|
|
IPerformanceStates20Info states = GPUApi.GetPerformanceStates20(internalGpu.Handle);
|
|
core = states.Clocks[PerformanceStateId.P0_3DPerformance][0].FrequencyDeltaInkHz.DeltaValue / 1000;
|
|
memory = states.Clocks[PerformanceStateId.P0_3DPerformance][1].FrequencyDeltaInkHz.DeltaValue / 1000;
|
|
Logger.WriteLine($"GET GPU CLOCKS: {core}, {memory}");
|
|
|
|
foreach (var delta in states.Voltages[PerformanceStateId.P0_3DPerformance])
|
|
{
|
|
Logger.WriteLine("GPU VOLT:" + delta.IsEditable + " - " + delta.ValueDeltaInMicroVolt.DeltaValue);
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.WriteLine("GET GPU CLOCKS:" + ex.Message);
|
|
core = memory = 0;
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private bool RunPowershellCommand(string script)
|
|
{
|
|
try
|
|
{
|
|
ProcessHelper.RunCMD("powershell", script);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.WriteLine(ex.ToString());
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
public int GetMaxGPUCLock()
|
|
{
|
|
PhysicalGPU internalGpu = _internalGpu!;
|
|
try
|
|
{
|
|
PrivateClockBoostLockV2 data = GPUApi.GetClockBoostLock(internalGpu.Handle);
|
|
int limit = (int)data.ClockBoostLocks[0].VoltageInMicroV / 1000;
|
|
Logger.WriteLine("GET CLOCK LIMIT: " + limit);
|
|
return limit;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.WriteLine("GET CLOCK LIMIT: " + ex.Message);
|
|
return -1;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
public int SetMaxGPUClock(int clock)
|
|
{
|
|
|
|
if (clock < MinClockLimit || clock >= MaxClockLimit) clock = 0;
|
|
|
|
int _clockLimit = GetMaxGPUCLock();
|
|
|
|
if (_clockLimit != clock)
|
|
{
|
|
if (clock > 0) RunPowershellCommand($"nvidia-smi -lgc 0,{clock}");
|
|
else RunPowershellCommand($"nvidia-smi -rgc");
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public bool RestartGPU()
|
|
{
|
|
return RunPowershellCommand(@"$device = Get-PnpDevice | Where-Object { $_.FriendlyName -imatch 'NVIDIA' -and $_.Class -eq 'Display' }; Disable-PnpDevice $device.InstanceId -Confirm:$false; Start-Sleep -Seconds 5; Enable-PnpDevice $device.InstanceId -Confirm:$false");
|
|
}
|
|
|
|
|
|
public int SetClocks(int core, int memory)
|
|
{
|
|
|
|
if (core < MinCoreOffset || core > MaxCoreOffset) return 0;
|
|
if (memory < MinMemoryOffset || memory > MaxMemoryOffset) return 0;
|
|
|
|
if (GetClocks(out int currentCore, out int currentMemory))
|
|
{
|
|
if (Math.Abs(core - currentCore) < 5 && Math.Abs(memory - currentMemory) < 5) return 0;
|
|
}
|
|
|
|
PhysicalGPU internalGpu = _internalGpu!;
|
|
|
|
var coreClock = new PerformanceStates20ClockEntryV1(PublicClockDomain.Graphics, new PerformanceStates20ParameterDelta(core * 1000));
|
|
var memoryClock = new PerformanceStates20ClockEntryV1(PublicClockDomain.Memory, new PerformanceStates20ParameterDelta(memory * 1000));
|
|
//var voltageEntry = new PerformanceStates20BaseVoltageEntryV1(PerformanceVoltageDomain.Core, new PerformanceStates20ParameterDelta(voltage));
|
|
|
|
PerformanceStates20ClockEntryV1[] clocks = { coreClock, memoryClock };
|
|
PerformanceStates20BaseVoltageEntryV1[] voltages = { };
|
|
|
|
PerformanceState20[] performanceStates = { new PerformanceState20(PerformanceStateId.P0_3DPerformance, clocks, voltages) };
|
|
|
|
var overclock = new PerformanceStates20InfoV1(performanceStates, 2, 0);
|
|
|
|
try
|
|
{
|
|
Logger.WriteLine($"SET GPU CLOCKS: {core}, {memory}");
|
|
GPUApi.SetPerformanceStates20(internalGpu.Handle, overclock);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.WriteLine("SET GPU CLOCKS: " + ex.Message);
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
private static PhysicalGPU? GetInternalDiscreteGpu()
|
|
{
|
|
try
|
|
{
|
|
return PhysicalGPU
|
|
.GetPhysicalGPUs()
|
|
.FirstOrDefault(gpu => gpu.SystemType == SystemType.Laptop);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.WriteLine(ex.Message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
public int? GetGpuUse()
|
|
{
|
|
if (!IsValid)
|
|
return null;
|
|
|
|
PhysicalGPU internalGpu = _internalGpu!;
|
|
IUtilizationDomainInfo? gpuUsage = GPUApi.GetUsages(internalGpu.Handle).GPU;
|
|
|
|
return (int?)gpuUsage?.Percentage;
|
|
|
|
}
|
|
|
|
}
|