From d5b098335bb1d3e3859d644003fcadeac22367bc Mon Sep 17 00:00:00 2001 From: Serge <5920850+seerge@users.noreply.github.com> Date: Sun, 4 Jun 2023 01:25:39 +0200 Subject: [PATCH] Kill GPU apps for AMD, Optimus fix --- app/Gpu/AmdAdl2.cs | 35 ++++++++++++ app/Gpu/AmdGpuControl.cs | 120 ++++++++++++++++++++++++++++++++------- app/Gpu/IGpuControl.cs | 3 + app/HardwareControl.cs | 5 +- app/NativeMethods.cs | 6 +- app/Program.cs | 2 - app/Settings.cs | 6 +- 7 files changed, 146 insertions(+), 31 deletions(-) diff --git a/app/Gpu/AmdAdl2.cs b/app/Gpu/AmdAdl2.cs index 8a0813d8..df92189a 100644 --- a/app/Gpu/AmdAdl2.cs +++ b/app/Gpu/AmdAdl2.cs @@ -5,6 +5,32 @@ namespace AmdAdl2; #region Export Struct +[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] +public struct ADLSGApplicationInfo +{ + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string strFileName; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string strFilePath; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string strVersion; + + public long timeStamp; + public uint iProfileExists; + public uint iGPUAffinity; + public ADLBdf GPUBdf; +} + +[StructLayout(LayoutKind.Sequential)] +public struct ADLBdf +{ + public int iBus; + public int iDevice; + public int iFunction; +} + [StructLayout(LayoutKind.Sequential)] public struct ADLSingleSensorData { public int Supported; @@ -481,5 +507,14 @@ public class Adl2 { [DllImport(Atiadlxx_FileName)] public static extern int ADL2_Adapter_ASICFamilyType_Get(IntPtr adlContextHandle, int adapterIndex, out ADLAsicFamilyType asicFamilyType, out int asicFamilyTypeValids); + + [DllImport(Atiadlxx_FileName)] + public static extern int ADL2_SwitchableGraphics_Applications_Get( + IntPtr context, + int iListType, + out int lpNumApps, + out IntPtr lppAppList); + + } } diff --git a/app/Gpu/AmdGpuControl.cs b/app/Gpu/AmdGpuControl.cs index 745674d9..3cd18a1e 100644 --- a/app/Gpu/AmdGpuControl.cs +++ b/app/Gpu/AmdGpuControl.cs @@ -1,10 +1,12 @@ -using System.Runtime.InteropServices; using AmdAdl2; +using System.Diagnostics; +using System.Runtime.InteropServices; namespace GHelper.Gpu; // Reference: https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Sample-Managed/Program.cs -public class AmdGpuControl : IGpuControl { +public class AmdGpuControl : IGpuControl +{ private bool _isReady; private IntPtr _adlContextHandle; private readonly ADLAdapterInfo _internalDiscreteAdapter; @@ -12,7 +14,8 @@ public class AmdGpuControl : IGpuControl { public bool IsNvidia => false; public string FullName => _internalDiscreteAdapter!.AdapterName; - public AmdGpuControl() { + public AmdGpuControl() + { if (!Adl2.Load()) return; @@ -30,29 +33,30 @@ public class AmdGpuControl : IGpuControl { if (Adl2.NativeMethods.ADL2_Adapter_AdapterInfo_Get(_adlContextHandle, AdapterBuffer, osAdapterInfoDataSize) != Adl2.ADL_SUCCESS) return; - osAdapterInfoData = (ADLAdapterInfoArray) Marshal.PtrToStructure(AdapterBuffer, osAdapterInfoData.GetType())!; + osAdapterInfoData = (ADLAdapterInfoArray)Marshal.PtrToStructure(AdapterBuffer, osAdapterInfoData.GetType())!; const int amdVendorId = 1002; - + // Determine which GPU is internal discrete AMD GPU - ADLAdapterInfo internalDiscreteAdapter = + ADLAdapterInfo internalDiscreteAdapter = osAdapterInfoData.ADLAdapterInfo - .FirstOrDefault(adapter => { + .FirstOrDefault(adapter => + { if (adapter.Exist == 0 || adapter.Present == 0) return false; - + if (adapter.VendorID != amdVendorId) return false; if (Adl2.NativeMethods.ADL2_Adapter_ASICFamilyType_Get(_adlContextHandle, adapter.AdapterIndex, out ADLAsicFamilyType asicFamilyType, out int asicFamilyTypeValids) != Adl2.ADL_SUCCESS) return false; - asicFamilyType = (ADLAsicFamilyType) ((int) asicFamilyType & asicFamilyTypeValids); - + asicFamilyType = (ADLAsicFamilyType)((int)asicFamilyType & asicFamilyTypeValids); + // FIXME: is this correct for G14 2022? - return (asicFamilyType & ADLAsicFamilyType.Discrete) != 0; + return (asicFamilyType & ADLAsicFamilyType.Discrete) != 0; }); - + if (internalDiscreteAdapter.Exist == 0) return; @@ -62,14 +66,15 @@ public class AmdGpuControl : IGpuControl { public bool IsValid => _isReady && _adlContextHandle != IntPtr.Zero; - public int? GetCurrentTemperature() { + public int? GetCurrentTemperature() + { if (!IsValid) return null; - + if (Adl2.NativeMethods.ADL2_New_QueryPMLogData_Get(_adlContextHandle, _internalDiscreteAdapter.AdapterIndex, out ADLPMLogDataOutput adlpmLogDataOutput) != Adl2.ADL_SUCCESS) return null; - - ADLSingleSensorData temperatureSensor = adlpmLogDataOutput.Sensors[(int) ADLSensorType.PMLOG_TEMPERATURE_EDGE]; + + ADLSingleSensorData temperatureSensor = adlpmLogDataOutput.Sensors[(int)ADLSensorType.PMLOG_TEMPERATURE_EDGE]; if (temperatureSensor.Supported == 0) return null; @@ -79,8 +84,7 @@ public class AmdGpuControl : IGpuControl { public int? GetGpuUse() { - if (!IsValid) - return null; + if (!IsValid) return null; if (Adl2.NativeMethods.ADL2_New_QueryPMLogData_Get(_adlContextHandle, _internalDiscreteAdapter.AdapterIndex, out ADLPMLogDataOutput adlpmLogDataOutput) != Adl2.ADL_SUCCESS) return null; @@ -93,21 +97,93 @@ public class AmdGpuControl : IGpuControl { } + public void KillGPUApps() + { - private void ReleaseUnmanagedResources() { - if (_adlContextHandle != IntPtr.Zero) { + if (!IsValid) return; + + IntPtr appInfoPtr = IntPtr.Zero; + int appCount = 0; + + try + { + // Get switchable graphics applications information + var result = Adl2.NativeMethods.ADL2_SwitchableGraphics_Applications_Get(_adlContextHandle, 2, out appCount, out appInfoPtr); + if (result != 0) + { + throw new Exception("Failed to get switchable graphics applications. Error code: " + result); + } + + // Convert the application data pointers to an array of structs + var appInfoArray = new ADLSGApplicationInfo[appCount]; + IntPtr currentPtr = appInfoPtr; + + for (int i = 0; i < appCount; i++) + { + appInfoArray[i] = Marshal.PtrToStructure(currentPtr); + currentPtr = IntPtr.Add(currentPtr, Marshal.SizeOf()); + } + + var appNames = new List(); + + for (int i = 0; i < appCount; i++) + { + if (appInfoArray[i].iGPUAffinity == 1) + { + Logger.WriteLine(appInfoArray[i].strFileName + ":" + appInfoArray[i].iGPUAffinity + "(" + appInfoArray[i].timeStamp + ")"); + appNames.Add(Path.GetFileNameWithoutExtension(appInfoArray[i].strFileName)); + } + } + + foreach (string kill in appNames) + foreach (var process in Process.GetProcessesByName(kill)) + { + try + { + process.Kill(); + Logger.WriteLine($"Stopped: {process.ProcessName}"); + } + catch (Exception ex) + { + Logger.WriteLine($"Failed to stop: {process.ProcessName} {ex.Message}"); + } + } + + + } catch (Exception ex) + { + Logger.WriteLine(ex.Message); + } + finally + { + // Clean up resources + if (appInfoPtr != IntPtr.Zero) + { + Marshal.FreeCoTaskMem(appInfoPtr); + } + + } + } + + + private void ReleaseUnmanagedResources() + { + if (_adlContextHandle != IntPtr.Zero) + { Adl2.NativeMethods.ADL2_Main_Control_Destroy(_adlContextHandle); _adlContextHandle = IntPtr.Zero; _isReady = false; } } - public void Dispose() { + public void Dispose() + { ReleaseUnmanagedResources(); GC.SuppressFinalize(this); } - ~AmdGpuControl() { + ~AmdGpuControl() + { ReleaseUnmanagedResources(); } } diff --git a/app/Gpu/IGpuControl.cs b/app/Gpu/IGpuControl.cs index 0fd640ca..b9cedcd1 100644 --- a/app/Gpu/IGpuControl.cs +++ b/app/Gpu/IGpuControl.cs @@ -6,4 +6,7 @@ public interface IGpuControl : IDisposable { public string FullName { get; } int? GetCurrentTemperature(); int? GetGpuUse(); + + void KillGPUApps(); + } diff --git a/app/HardwareControl.cs b/app/HardwareControl.cs index 85b27149..092151e8 100644 --- a/app/HardwareControl.cs +++ b/app/HardwareControl.cs @@ -210,10 +210,9 @@ public static class HardwareControl } } - if (AppConfig.isConfig("kill_gpu_apps") && GpuControl is not null && GpuControl.IsNvidia) + if (AppConfig.isConfig("kill_gpu_apps") && GpuControl is not null) { - NvidiaGpuControl nvControl = (NvidiaGpuControl)GpuControl; - nvControl.KillGPUApps(); + GpuControl.KillGPUApps(); } } } diff --git a/app/NativeMethods.cs b/app/NativeMethods.cs index bcf181bc..df41e59c 100644 --- a/app/NativeMethods.cs +++ b/app/NativeMethods.cs @@ -600,12 +600,16 @@ public class NativeMethods var devices = GetAllDevices().ToArray(); int count = 0, displayNum = -1; + string internalName = AppConfig.getConfigString("internal_display"); + foreach (var device in devices) { if (device.outputTechnology == DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL || - device.outputTechnology == DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED) + device.outputTechnology == DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED || + device.monitorFriendlyDeviceName == internalName) { displayNum = count; + AppConfig.setConfig("internal_display", device.monitorFriendlyDeviceName); } count++; //Logger.WriteLine(device.monitorFriendlyDeviceName + ":" + device.outputTechnology.ToString()); diff --git a/app/Program.cs b/app/Program.cs index ba159ce5..9b48ec85 100644 --- a/app/Program.cs +++ b/app/Program.cs @@ -100,8 +100,6 @@ namespace GHelper SettingsToggle(action); } - - Application.Run(); } diff --git a/app/Settings.cs b/app/Settings.cs index 0715655c..98a1735d 100644 --- a/app/Settings.cs +++ b/app/Settings.cs @@ -6,7 +6,6 @@ using System.Net; using System.Reflection; using System.Text.Json; using System.Timers; -using Tools; namespace GHelper { @@ -368,7 +367,8 @@ namespace GHelper string url = null; - for (int i = 0; i < assets.GetArrayLength(); i++) { + for (int i = 0; i < assets.GetArrayLength(); i++) + { if (assets[i].GetProperty("browser_download_url").ToString().Contains(".zip")) url = assets[i].GetProperty("browser_download_url").ToString(); } @@ -1301,7 +1301,7 @@ namespace GHelper public void AutoKeyboard() { InputDispatcher.SetBacklightAuto(true); - if (AppConfig.ContainsModel("X16") || AppConfig.ContainsModel("X13")) InputDispatcher.TabletMode(); + if (AppConfig.ContainsModel("X16") || AppConfig.ContainsModel("X13")) InputDispatcher.TabletMode(); }