aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Ava/UI
diff options
context:
space:
mode:
authorTSRBerry <20988865+TSRBerry@users.noreply.github.com>2023-05-30 01:48:37 +0200
committerGitHub <noreply@github.com>2023-05-30 01:48:37 +0200
commit35d91a0e58cb0b2916b7a4f138c63fcc12b71112 (patch)
tree4735140e36567ddaefb9089e9a0d5685b5f9079f /src/Ryujinx.Ava/UI
parenta73a5d7e85e4008a7d8c7eb8abd6bae80b950bba (diff)
Linux: Automatically increase vm.max_map_count if it's too low (#4702)
* memory: Check results of pinvoke calls * Increase vm.max_map_count when running Ryujinx * Add SupportedOSPlatform attribute for WindowsApiException * Revert increasing vm.max_map_count via script * Add LinuxHelper to detect and increase vm.max_map_count With GUI dialogs, this should be a bit more user-friendly. * Supply arguments as a list to RunPkExec * Add error logging in case RunPkExec() fails * Prevent Gtk from crashing
Diffstat (limited to 'src/Ryujinx.Ava/UI')
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs7
-rw-r--r--src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs74
2 files changed, 76 insertions, 5 deletions
diff --git a/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs b/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
index cb474506..d85895fc 100644
--- a/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
@@ -6,7 +6,6 @@ using Avalonia.Threading;
using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Logging;
using System;
@@ -19,7 +18,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
private static bool _isChoiceDialogOpen;
- public async static Task<UserResult> ShowContentDialog(
+ private async static Task<UserResult> ShowContentDialog(
string title,
object content,
string primaryButton,
@@ -67,7 +66,7 @@ namespace Ryujinx.Ava.UI.Helpers
return result;
}
- private async static Task<UserResult> ShowTextDialog(
+ public async static Task<UserResult> ShowTextDialog(
string title,
string primaryText,
string secondaryText,
@@ -319,7 +318,7 @@ namespace Ryujinx.Ava.UI.Helpers
Window parent = GetMainWindow();
- if (parent != null && parent.IsActive && parent is MainWindow window && window.ViewModel.IsGameRunning)
+ if (parent is { IsActive: true } and MainWindow window && window.ViewModel.IsGameRunning)
{
contentDialogOverlayWindow = new()
{
diff --git a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
index eec77479..cf84807e 100644
--- a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
@@ -23,6 +23,7 @@ using Ryujinx.Ui.Common.Helper;
using System;
using System.ComponentModel;
using System.IO;
+using System.Runtime.Versioning;
using System.Threading.Tasks;
using InputManager = Ryujinx.Input.HLE.InputManager;
@@ -258,7 +259,64 @@ namespace Ryujinx.Ava.UI.Windows
ApplicationHelper.Initialize(VirtualFileSystem, AccountManager, LibHacHorizonManager.RyujinxClient, this);
}
- protected void CheckLaunchState()
+ [SupportedOSPlatform("linux")]
+ private static async void ShowVmMaxMapCountWarning()
+ {
+ LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountWarningTextSecondary,
+ LinuxHelper.VmMaxMapCount, LinuxHelper.RecommendedVmMaxMapCount);
+
+ await ContentDialogHelper.CreateWarningDialog(
+ LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountWarningTextPrimary],
+ LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountWarningTextSecondary]
+ );
+ }
+
+ [SupportedOSPlatform("linux")]
+ private static async void ShowVmMaxMapCountDialog()
+ {
+ LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary,
+ LinuxHelper.RecommendedVmMaxMapCount);
+
+ UserResult response = await ContentDialogHelper.ShowTextDialog(
+ $"Ryujinx - {LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTitle]}",
+ LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary],
+ LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogTextSecondary],
+ LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogButtonUntilRestart],
+ LocaleManager.Instance[LocaleKeys.LinuxVmMaxMapCountDialogButtonPersistent],
+ LocaleManager.Instance[LocaleKeys.InputDialogNo],
+ (int)Symbol.Help
+ );
+
+ int rc;
+
+ switch (response)
+ {
+ case UserResult.Ok:
+ rc = LinuxHelper.RunPkExec($"echo {LinuxHelper.RecommendedVmMaxMapCount} > {LinuxHelper.VmMaxMapCountPath}");
+ if (rc == 0)
+ {
+ Logger.Info?.Print(LogClass.Application, $"vm.max_map_count set to {LinuxHelper.VmMaxMapCount} until the next restart.");
+ }
+ else
+ {
+ Logger.Error?.Print(LogClass.Application, $"Unable to change vm.max_map_count. Process exited with code: {rc}");
+ }
+ break;
+ case UserResult.No:
+ rc = LinuxHelper.RunPkExec($"echo \"vm.max_map_count = {LinuxHelper.RecommendedVmMaxMapCount}\" > {LinuxHelper.SysCtlConfigPath} && sysctl -p {LinuxHelper.SysCtlConfigPath}");
+ if (rc == 0)
+ {
+ Logger.Info?.Print(LogClass.Application, $"vm.max_map_count set to {LinuxHelper.VmMaxMapCount}. Written to config: {LinuxHelper.SysCtlConfigPath}");
+ }
+ else
+ {
+ Logger.Error?.Print(LogClass.Application, $"Unable to write new value for vm.max_map_count to config. Process exited with code: {rc}");
+ }
+ break;
+ }
+ }
+
+ private void CheckLaunchState()
{
if (ShowKeyErrorOnLoad)
{
@@ -268,6 +326,20 @@ namespace Ryujinx.Ava.UI.Windows
UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys, this));
}
+ if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount)
+ {
+ Logger.Warning?.Print(LogClass.Application, $"The value of vm.max_map_count is lower than {LinuxHelper.RecommendedVmMaxMapCount}. ({LinuxHelper.VmMaxMapCount})");
+
+ if (LinuxHelper.PkExecPath is not null)
+ {
+ Dispatcher.UIThread.Post(ShowVmMaxMapCountDialog);
+ }
+ else
+ {
+ Dispatcher.UIThread.Post(ShowVmMaxMapCountWarning);
+ }
+ }
+
if (_deferLoad)
{
_deferLoad = false;