TryingSandBox.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. using System;
  2. using System.IO;
  3. using System.IO.MemoryMappedFiles;
  4. using System.Runtime.InteropServices;
  5. using System.Threading;
  6. namespace GpuFanControl.MsiAfterburnerWrap
  7. {
  8. using ShareMemoryStructs;
  9. namespace ShareMemoryStructs
  10. {
  11. [Serializable]
  12. public struct MACM_SHARED_MEMORY_HEADER
  13. {
  14. public uint signature;
  15. public uint version;
  16. public uint headerSize;
  17. public uint gpuEntryCount;
  18. public uint gpuEntrySize;
  19. public uint masterGpu;
  20. public MACM_SHARED_MEMORY_FLAG flags;
  21. public uint time;
  22. public MACM_SHARED_MEMORY_COMMAND command;
  23. }
  24. [Flags]
  25. public enum MACM_SHARED_MEMORY_FLAG : uint
  26. {
  27. None = 0,
  28. LINK = 1,
  29. SYNC = 2,
  30. THERMAL = 4,
  31. }
  32. [Flags]
  33. public enum MACM_SHARED_MEMORY_COMMAND : uint
  34. {
  35. None = 0,
  36. INIT = 11206656, // 0x00AB0000
  37. FLUSH = 11206657, // 0x00AB0001
  38. }
  39. [Serializable]
  40. public struct MACM_SHARED_MEMORY_GPU_ENTRY
  41. {
  42. public MACM_SHARED_MEMORY_GPU_ENTRY_FLAG flags;
  43. public uint coreClockCur;
  44. public uint coreClockMin;
  45. public uint coreClockMax;
  46. public uint coreClockDef;
  47. public uint shaderClockCur;
  48. public uint shaderClockMin;
  49. public uint shaderClockMax;
  50. public uint shaderClockDef;
  51. public uint memoryClockCur;
  52. public uint memoryClockMin;
  53. public uint memoryClockMax;
  54. public uint memoryClockDef;
  55. public uint fanSpeedCur;
  56. public MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG fanFlagsCur;
  57. public uint fanSpeedMin;
  58. public uint fanSpeedMax;
  59. public uint fanSpeedDef;
  60. public MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG fanFlagsDef;
  61. public uint coreVoltageCur;
  62. public uint coreVoltageMin;
  63. public uint coreVoltageMax;
  64. public uint coreVoltageDef;
  65. public uint memoryVoltageCur;
  66. public uint memoryVoltageMin;
  67. public uint memoryVoltageMax;
  68. public uint memoryVoltageDef;
  69. public uint auxVoltageCur;
  70. public uint auxVoltageMin;
  71. public uint auxVoltageMax;
  72. public uint auxVoltageDef;
  73. public int coreVoltageBoostCur;
  74. public int coreVoltageBoostMin;
  75. public int coreVoltageBoostMax;
  76. public int coreVoltageBoostDef;
  77. public int memoryVoltageBoostCur;
  78. public int memoryVoltageBoostMin;
  79. public int memoryVoltageBoostMax;
  80. public int memoryVoltageBoostDef;
  81. public int auxVoltageBoostCur;
  82. public int auxVoltageBoostMin;
  83. public int auxVoltageBoostMax;
  84. public int auxVoltageBoostDef;
  85. public int powerLimitCur;
  86. public int powerLimitMin;
  87. public int powerLimitMax;
  88. public int powerLimitDef;
  89. public int coreClockBoostCur;
  90. public int coreClockBoostMin;
  91. public int coreClockBoostMax;
  92. public int coreClockBoostDef;
  93. public int memoryClockBoostCur;
  94. public int memoryClockBoostMin;
  95. public int memoryClockBoostMax;
  96. public int memoryClockBoostDef;
  97. public int thermalLimitCur;
  98. public int thermalLimitMin;
  99. public int thermalLimitMax;
  100. public int thermalLimitDef;
  101. public uint thermalPrioritizeCur;
  102. public uint thermalPrioritizeDef;
  103. }
  104. [Flags]
  105. public enum MACM_SHARED_MEMORY_GPU_ENTRY_FLAG : uint
  106. {
  107. None = 0,
  108. CORE_CLOCK = 1,
  109. SHADER_CLOCK = 2,
  110. MEMORY_CLOCK = 4,
  111. FAN_SPEED = 8,
  112. CORE_VOLTAGE = 16, // 0x00000010
  113. MEMORY_VOLTAGE = 32, // 0x00000020
  114. AUX_VOLTAGE = 64, // 0x00000040
  115. CORE_VOLTAGE_BOOST = 128, // 0x00000080
  116. MEMORY_VOLTAGE_BOOST = 256, // 0x00000100
  117. AUX_VOLTAGE_BOOST = 512, // 0x00000200
  118. POWER_LIMIT = 1024, // 0x00000400
  119. CORE_CLOCK_BOOST = 2048, // 0x00000800
  120. MEMORY_CLOCK_BOOST = 4096, // 0x00001000
  121. THERMAL_LIMIT = 8192, // 0x00002000
  122. THERMAL_PRIORITIZE = 16384, // 0x00004000
  123. SYNCHRONIZED_WITH_MASTER = 2147483648, // 0x80000000
  124. }
  125. [Flags]
  126. public enum MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG : uint
  127. {
  128. None = 0,
  129. AUTO = 1,
  130. }
  131. }
  132. internal class MsiAfterBurnControlWrap
  133. {
  134. //const
  135. private const string ShareMemoryName = "MACMSharedMemory";
  136. private const string MutexName = "Global\\Access_MACMSharedMemory";
  137. private const uint HeaderSignature = ('M' << 24 | ('A' << 16) | ('C' << 8) | ('M'));
  138. private MemoryMappedFile _hMapFile;
  139. private MemoryMappedViewStream _pMapAddr;
  140. private byte[] _bufSnap;
  141. public void Connect()
  142. {
  143. //connect , failure throws FileNotFoundException
  144. _hMapFile = MemoryMappedFile.OpenExisting(ShareMemoryName, MemoryMappedFileRights.FullControl);
  145. _pMapAddr = _hMapFile.CreateViewStream();
  146. //var x_pMapAddr = _hMapFile.CreateViewAccessor();
  147. }
  148. public void Disconnect()
  149. {
  150. _pMapAddr?.Close();
  151. _hMapFile?.Dispose();
  152. }
  153. public void Refresh()
  154. {
  155. using (var m = new Mutex(false, MutexName))
  156. {
  157. m.WaitOne();
  158. var lenHeader = Marshal.SizeOf(typeof(MACM_SHARED_MEMORY_HEADER));
  159. var bufHeader = new byte[lenHeader];
  160. _pMapAddr.Seek(0, SeekOrigin.Begin);
  161. _pMapAddr.Read(bufHeader, 0, lenHeader);
  162. var stHeader = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(bufHeader);
  163. if (stHeader.signature == HeaderSignature)
  164. {
  165. var lenSnap = stHeader.headerSize + stHeader.gpuEntryCount * stHeader.gpuEntrySize;
  166. var bufSnap = new byte[lenSnap];
  167. _pMapAddr.Seek(0, SeekOrigin.Begin);
  168. _pMapAddr.Read(bufSnap, 0, (int)lenSnap);
  169. _bufSnap = bufSnap;
  170. }
  171. m.ReleaseMutex();
  172. }
  173. }
  174. public void Commit()
  175. {
  176. using (var m = new Mutex(false, MutexName))
  177. {
  178. m.WaitOne();
  179. _pMapAddr.Seek(0, SeekOrigin.Begin);
  180. _pMapAddr.Write(_bufSnap, 0, _bufSnap.Length);
  181. _pMapAddr.Flush();
  182. _pMapAddr.Seek(0, SeekOrigin.Begin);
  183. var header = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(_bufSnap);
  184. header.command = MACM_SHARED_MEMORY_COMMAND.FLUSH;
  185. StructToByteArray(header, _bufSnap);
  186. _pMapAddr.Seek(0, SeekOrigin.Begin);
  187. _pMapAddr.Write(_bufSnap, 0, _bufSnap.Length);
  188. _pMapAddr.Flush();
  189. m.ReleaseMutex();
  190. }
  191. Refresh();
  192. }
  193. public int GetNumberOfGpu()
  194. {
  195. var st = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(_bufSnap);
  196. return (int)st.gpuEntryCount;
  197. }
  198. public MACM_SHARED_MEMORY_GPU_ENTRY? GetGpuEntry(int index, out string error)
  199. {
  200. var header = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(_bufSnap);
  201. if (index > header.gpuEntryCount || index < 0)
  202. {
  203. error = "index out of range";
  204. return null;
  205. }
  206. var entry = ByteArrayToStruct<MACM_SHARED_MEMORY_GPU_ENTRY>(_bufSnap, (int)header.headerSize + index * (int)header.gpuEntrySize);
  207. error = null;
  208. return entry;
  209. }
  210. public string SetGpuEntry(MACM_SHARED_MEMORY_GPU_ENTRY entry, int index, bool flush = false)
  211. {
  212. var header = ByteArrayToStruct<MACM_SHARED_MEMORY_HEADER>(_bufSnap);
  213. if (index > header.gpuEntryCount || index < 0) return "index out of range";
  214. StructToByteArray(entry, _bufSnap, (int)(header.headerSize + index * header.gpuEntrySize));
  215. if (flush) Commit();
  216. return null;
  217. }
  218. private T ByteArrayToStruct<T>(byte[] bytes, int offset = 0)
  219. {
  220. GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
  221. T stuff;
  222. try
  223. {
  224. stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject() + offset, typeof(T));
  225. }
  226. finally
  227. {
  228. handle.Free();
  229. }
  230. return stuff;
  231. }
  232. private static void StructToByteArray<T>(T str, byte[] snap, int offset = 0)
  233. {
  234. var h = default(GCHandle);
  235. try
  236. {
  237. h = GCHandle.Alloc(snap, GCHandleType.Pinned);
  238. Marshal.StructureToPtr<T>(str, h.AddrOfPinnedObject() + offset, false);
  239. }
  240. finally
  241. {
  242. if (h.IsAllocated)
  243. {
  244. h.Free();
  245. }
  246. }
  247. }
  248. }
  249. internal class TryingSandBox
  250. {
  251. public static void Go()
  252. {
  253. var ctl = new MsiAfterBurnControlWrap();
  254. ctl.Connect();
  255. ctl.Refresh();
  256. var numberOfGpu = ctl.GetNumberOfGpu();
  257. for (int i = 0; i < numberOfGpu; i++)
  258. {
  259. Console.WriteLine($"Get entry of GPU #{i}");
  260. MACM_SHARED_MEMORY_GPU_ENTRY? g;
  261. {
  262. g = ctl.GetGpuEntry(i, out string err);
  263. if (g.HasValue == false)
  264. {
  265. Console.WriteLine($"Err:{err}");
  266. continue;
  267. }
  268. }
  269. var entry = g.Value;
  270. if (entry.flags.HasFlag(MACM_SHARED_MEMORY_GPU_ENTRY_FLAG.FAN_SPEED))
  271. {
  272. Console.WriteLine($"Updating fan speed of GPU #{i}");
  273. //entry.fanFlagsCur = MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG.AUTO;
  274. entry.fanFlagsCur = MACM_SHARED_MEMORY_GPU_ENTRY_FAN_FLAG.None;
  275. entry.fanSpeedCur = entry.fanSpeedMax;
  276. var err=ctl.SetGpuEntry(entry, i);
  277. if(err!=null) Console.WriteLine($"Err: {err}");
  278. }
  279. else
  280. {
  281. Console.WriteLine($"Err: No support fan speed");
  282. }
  283. }
  284. Console.WriteLine("Commiting...");
  285. ctl.Commit();
  286. Console.WriteLine("Success");
  287. ctl.Disconnect();
  288. }
  289. }
  290. }