123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- using System;
- using System.IO;
- using System.IO.MemoryMappedFiles;
- using System.Runtime.InteropServices;
- using System.Threading;
- namespace GpuFanControl.MsiAfterburnerWrap
- {
- using ShareMemoryStructs;
- namespace ShareMemoryStructs
- {
- [Serializable]
- public struct MACM_SHARED_MEMORY_HEADER
- {
- public uint signature;
- public uint version;
- public uint headerSize;
- public uint gpuEntryCount;
- public uint gpuEntrySize;
- public uint masterGpu;
- public MACM_SHARED_MEMORY_FLAG flags;
- public uint time;
- public MACM_SHARED_MEMORY_COMMAND command;
- }
- [Flags]
- public enum MACM_SHARED_MEMORY_FLAG : uint
- {
- None = 0,
- LINK = 1,
- SYNC = 2,
- THERMAL = 4,
- }
- [Flags]
- public enum MACM_SHARED_MEMORY_COMMAND : uint
- {
- None = 0,
- INIT = 11206656, // 0x00AB0000
- FLUSH = 11206657, // 0x00AB0001
- }
- [Serializable]
- public struct MACM_SHARED_MEMORY_GPU_ENTRY
- {
- public MACM_SHARED_MEMORY_GPU_ENTRY_FLAG flags;
- public uint coreClockCur;
- public uint coreClockMin;
- public uint coreClockMax;
- public uint coreClockDef;
- public uint shaderClockCur;
- public uint shaderClockMin;
- public uint shaderClockMax;
- public uint shaderClockDef;
- public uint memoryClockCur;
- public uint memoryClockMin;
- public uint memoryClockMax;
- public uint memoryClockDef;
- public uint fanSpeedCur;
- public MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG fanFlagsCur;
- public uint fanSpeedMin;
- public uint fanSpeedMax;
- public uint fanSpeedDef;
- public MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG fanFlagsDef;
- public uint coreVoltageCur;
- public uint coreVoltageMin;
- public uint coreVoltageMax;
- public uint coreVoltageDef;
- public uint memoryVoltageCur;
- public uint memoryVoltageMin;
- public uint memoryVoltageMax;
- public uint memoryVoltageDef;
- public uint auxVoltageCur;
- public uint auxVoltageMin;
- public uint auxVoltageMax;
- public uint auxVoltageDef;
- public int coreVoltageBoostCur;
- public int coreVoltageBoostMin;
- public int coreVoltageBoostMax;
- public int coreVoltageBoostDef;
- public int memoryVoltageBoostCur;
- public int memoryVoltageBoostMin;
- public int memoryVoltageBoostMax;
- public int memoryVoltageBoostDef;
- public int auxVoltageBoostCur;
- public int auxVoltageBoostMin;
- public int auxVoltageBoostMax;
- public int auxVoltageBoostDef;
- public int powerLimitCur;
- public int powerLimitMin;
- public int powerLimitMax;
- public int powerLimitDef;
- public int coreClockBoostCur;
- public int coreClockBoostMin;
- public int coreClockBoostMax;
- public int coreClockBoostDef;
- public int memoryClockBoostCur;
- public int memoryClockBoostMin;
- public int memoryClockBoostMax;
- public int memoryClockBoostDef;
- public int thermalLimitCur;
- public int thermalLimitMin;
- public int thermalLimitMax;
- public int thermalLimitDef;
- public uint thermalPrioritizeCur;
- public uint thermalPrioritizeDef;
- }
- [Flags]
- public enum MACM_SHARED_MEMORY_GPU_ENTRY_FLAG : uint
- {
- None = 0,
- CORE_CLOCK = 1,
- SHADER_CLOCK = 2,
- MEMORY_CLOCK = 4,
- FAN_SPEED = 8,
- CORE_VOLTAGE = 16, // 0x00000010
- MEMORY_VOLTAGE = 32, // 0x00000020
- AUX_VOLTAGE = 64, // 0x00000040
- CORE_VOLTAGE_BOOST = 128, // 0x00000080
- MEMORY_VOLTAGE_BOOST = 256, // 0x00000100
- AUX_VOLTAGE_BOOST = 512, // 0x00000200
- POWER_LIMIT = 1024, // 0x00000400
- CORE_CLOCK_BOOST = 2048, // 0x00000800
- MEMORY_CLOCK_BOOST = 4096, // 0x00001000
- THERMAL_LIMIT = 8192, // 0x00002000
- THERMAL_PRIORITIZE = 16384, // 0x00004000
- SYNCHRONIZED_WITH_MASTER = 2147483648, // 0x80000000
- }
- [Flags]
- public enum MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG : uint
- {
- None = 0,
- AUTO = 1,
- }
- }
- internal class MsiAfterBurnControlWrap
- {
- //const
- private const string ShareMemoryName = "MACMSharedMemory";
- private const string MutexName = "Global\\Access_MACMSharedMemory";
- private const uint HeaderSignature = ('M' << 24 | ('A' << 16) | ('C' << 8) | ('M'));
- private MemoryMappedFile _hMapFile;
- private MemoryMappedViewStream _pMapAddr;
- private byte[] _bufSnap;
- public void Connect()
- {
- //connect , failure throws FileNotFoundException
- _hMapFile = MemoryMappedFile.OpenExisting(ShareMemoryName, MemoryMappedFileRights.FullControl);
- _pMapAddr = _hMapFile.CreateViewStream();
- //var x_pMapAddr = _hMapFile.CreateViewAccessor();
- }
- public void Disconnect()
- {
- _pMapAddr?.Close();
- _hMapFile?.Dispose();
- }
- public void Refresh()
- {
- using (var m = new Mutex(false, MutexName))
- {
- m.WaitOne();
- var lenHeader = Marshal.SizeOf(typeof(MACM_SHARED_MEMORY_HEADER));
- var bufHeader = new byte[lenHeader];
- _pMapAddr.Seek(0, SeekOrigin.Begin);
- _pMapAddr.Read(bufHeader, 0, lenHeader);
- var stHeader = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(bufHeader);
- if (stHeader.signature == HeaderSignature)
- {
- var lenSnap = stHeader.headerSize + stHeader.gpuEntryCount * stHeader.gpuEntrySize;
- var bufSnap = new byte[lenSnap];
- _pMapAddr.Seek(0, SeekOrigin.Begin);
- _pMapAddr.Read(bufSnap, 0, (int)lenSnap);
- _bufSnap = bufSnap;
- }
- m.ReleaseMutex();
- }
- }
- public void Commit()
- {
- using (var m = new Mutex(false, MutexName))
- {
- m.WaitOne();
- _pMapAddr.Seek(0, SeekOrigin.Begin);
- _pMapAddr.Write(_bufSnap, 0, _bufSnap.Length);
- _pMapAddr.Flush();
- _pMapAddr.Seek(0, SeekOrigin.Begin);
- var header = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(_bufSnap);
- header.command = MACM_SHARED_MEMORY_COMMAND.FLUSH;
- StructToByteArray(header, _bufSnap);
- _pMapAddr.Seek(0, SeekOrigin.Begin);
- _pMapAddr.Write(_bufSnap, 0, _bufSnap.Length);
- _pMapAddr.Flush();
- m.ReleaseMutex();
- }
- Refresh();
- }
- public int GetNumberOfGpu()
- {
- var st = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(_bufSnap);
- return (int)st.gpuEntryCount;
- }
- public MACM_SHARED_MEMORY_GPU_ENTRY? GetGpuEntry(int index, out string error)
- {
- var header = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(_bufSnap);
- if (index > header.gpuEntryCount || index < 0)
- {
- error = "index out of range";
- return null;
- }
- var entry = ByteArrayToStruct<MACM_SHARED_MEMORY_GPU_ENTRY>(_bufSnap, (int)header.headerSize + index * (int)header.gpuEntrySize);
- error = null;
- return entry;
- }
- public string SetGpuEntry(MACM_SHARED_MEMORY_GPU_ENTRY entry, int index, bool flush = false)
- {
- var header = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(_bufSnap);
- if (index > header.gpuEntryCount || index < 0) return "index out of range";
- StructToByteArray(entry, _bufSnap, (int)(header.headerSize + index * header.gpuEntrySize));
- if (flush) Commit();
- return null;
- }
- private T ByteArrayToStruct<T>(byte[] bytes, int offset = 0)
- {
- GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
- T stuff;
- try
- {
- stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject() + offset, typeof(T));
- }
- finally
- {
- handle.Free();
- }
- return stuff;
- }
- private static void StructToByteArray<T>(T str, byte[] snap, int offset = 0)
- {
- var h = default(GCHandle);
- try
- {
- h = GCHandle.Alloc(snap, GCHandleType.Pinned);
- Marshal.StructureToPtr<T>(str, h.AddrOfPinnedObject() + offset, false);
- }
- finally
- {
- if (h.IsAllocated)
- {
- h.Free();
- }
- }
- }
- }
- internal class TryingSandBox
- {
- public static void Go()
- {
- var ctl = new MsiAfterBurnControlWrap();
- ctl.Connect();
- ctl.Refresh();
- var numberOfGpu = ctl.GetNumberOfGpu();
- for (int i = 0; i < numberOfGpu; i++)
- {
- Console.WriteLine($"Get entry of GPU #{i}");
- MACM_SHARED_MEMORY_GPU_ENTRY? g;
- {
- g = ctl.GetGpuEntry(i, out string err);
- if (g.HasValue == false)
- {
- Console.WriteLine($"Err:{err}");
- continue;
- }
- }
- var entry = g.Value;
- if (entry.flags.HasFlag(MACM_SHARED_MEMORY_GPU_ENTRY_FLAG.FAN_SPEED))
- {
- Console.WriteLine($"Updating fan speed of GPU #{i}");
- //entry.fanFlagsCur = MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG.AUTO;
- entry.fanFlagsCur = MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG.None;
- entry.fanSpeedCur = entry.fanSpeedMax;
- var err=ctl.SetGpuEntry(entry, i);
- if(err!=null) Console.WriteLine($"Err: {err}");
- }
- else
- {
- Console.WriteLine($"Err: No support fan speed");
- }
- }
- Console.WriteLine("Commiting...");
- ctl.Commit();
- Console.WriteLine("Success");
- ctl.Disconnect();
- }
- }
- }
|