diff --git a/ClientGUI/GameProcessLogic.cs b/ClientGUI/GameProcessLogic.cs index 41a51b62b..4f28414dd 100644 --- a/ClientGUI/GameProcessLogic.cs +++ b/ClientGUI/GameProcessLogic.cs @@ -1,13 +1,17 @@ using System; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Runtime.InteropServices; +using System.Threading; + using ClientCore; -using Rampastring.Tools; +using ClientCore.Enums; +using ClientCore.Extensions; using ClientCore.INIProcessing; -using System.Threading; + +using Rampastring.Tools; using Rampastring.XNAUI; -using ClientCore.Extensions; namespace ClientGUI { @@ -25,6 +29,35 @@ public static class GameProcessLogic public static bool UseQres { get; set; } public static bool SingleCoreAffinity { get; set; } + public static bool GetProcessorAffinityValue(out int affinity) + { + if (!(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))) + { + affinity = 0; + return false; + } + + if (Environment.ProcessorCount <= 1) + { + affinity = 1; // Only one CPU core available + return true; + } + + + if (SingleCoreAffinity) + { + affinity = 2; // Use only CPU 1 + return true; + } + else + { + int maximumCpuCountPerProcessorGroup = 64; + int cpuCount = Math.Min(Environment.ProcessorCount, maximumCpuCountPerProcessorGroup); + affinity = (1 << cpuCount) - 2; // All but CPU 0 + return true; + } + } + /// /// Starts the main game process. /// @@ -83,6 +116,8 @@ public static void StartGameProcess(WindowManager windowManager) GameProcessStarting?.Invoke(); + bool overrideProcessorAffinity = GetProcessorAffinityValue(out int processorAffinity); + if (UserINISettings.Instance.WindowedMode && UseQres && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Logger.Log("Windowed mode is enabled - using QRes."); @@ -112,8 +147,8 @@ public static void StartGameProcess(WindowManager windowManager) return; } - if (Environment.ProcessorCount > 1 && SingleCoreAffinity) - QResProcess.ProcessorAffinity = (IntPtr)2; + if (overrideProcessorAffinity) + QResProcess.ProcessorAffinity = (IntPtr)processorAffinity; } else { @@ -124,6 +159,12 @@ public static void StartGameProcess(WindowManager windowManager) else arguments = additionalExecutableName + "-SPAWN"; + if (overrideProcessorAffinity && ClientConfiguration.Instance.ClientGameType == ClientType.Ares) + { + // Ares defaults to use CPU 0 exclusively, unless explicitly overridden. + arguments += " " + "-AFFINITY:" + processorAffinity.ToString(CultureInfo.InvariantCulture); + } + FileInfo gameFileInfo = SafePath.GetFile(ProgramConstants.GamePath, gameExecutableName); var gameProcess = new Process(); @@ -151,11 +192,8 @@ public static void StartGameProcess(WindowManager windowManager) return; } - if ((RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - && Environment.ProcessorCount > 1 && SingleCoreAffinity) - { - gameProcess.ProcessorAffinity = (IntPtr)2; - } + if (overrideProcessorAffinity) + gameProcess.ProcessorAffinity = (IntPtr)processorAffinity; } GameProcessStarted?.Invoke();