From c9b2a6b1f155b45ee7385be0e1532a1c95fd13a8 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Thu, 26 Dec 2024 22:42:39 -0600 Subject: [PATCH 01/14] metal: Try and see if this lets VSync turn off. (cherry picked from commit 9558b3771634d144501dedf3f081afc485a49d9d) --- Ryujinx.sln | 11 ++++++++-- .../CAMetalLayerExtensions.cs | 21 +++++++++++++++++++ ...Graphics.Metal.SharpMetalExtensions.csproj | 10 +++++++++ .../Ryujinx.Graphics.Metal.csproj | 9 +++----- src/Ryujinx.Graphics.Metal/Window.cs | 11 +++++++++- 5 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs create mode 100644 src/Ryujinx.Graphics.Metal.SharpMetalExtensions/Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj diff --git a/Ryujinx.sln b/Ryujinx.sln index 71d5f6dd9..e9f57df39 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -80,11 +80,16 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}" ProjectSection(ProjectDependencies) = postProject {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} = {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal.SharpMetalExtensions", "src/Ryujinx.Graphics.Metal.SharpMetalExtensions\Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj", "{81EA598C-DBA1-40B0-8DA4-4796B78F2037}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig @@ -94,8 +99,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .github\workflows\release.yml = .github\workflows\release.yml EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -265,6 +268,10 @@ Global {C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU + {81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs b/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs new file mode 100644 index 000000000..361419658 --- /dev/null +++ b/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs @@ -0,0 +1,21 @@ +using SharpMetal; +using SharpMetal.ObjectiveCCore; +using SharpMetal.QuartzCore; +using System.Runtime.Versioning; +// ReSharper disable InconsistentNaming + +namespace Ryujinx.Graphics.Metal.SharpMetalExtensions +{ + [SupportedOSPlatform("OSX")] + public static class CAMetalLayerExtensions + { + private static readonly Selector sel_displaySyncEnabled = "displaySyncEnabled"; + private static readonly Selector sel_setDisplaySyncEnabled = "setDisplaySyncEnabled:"; + + public static bool IsDisplaySyncEnabled(this CAMetalLayer metalLayer) + => ObjectiveCRuntime.bool_objc_msgSend(metalLayer.NativePtr, sel_displaySyncEnabled); + + public static void SetDisplaySyncEnabled(this CAMetalLayer metalLayer, bool enabled) + => ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDisplaySyncEnabled, enabled); + } +} diff --git a/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj b/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj new file mode 100644 index 000000000..9836063a3 --- /dev/null +++ b/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj @@ -0,0 +1,10 @@ + + + enable + enable + + + + + + diff --git a/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj b/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj index 02afb150a..364aa5a8b 100644 --- a/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj +++ b/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj @@ -5,12 +5,9 @@ - - - - - - + + + diff --git a/src/Ryujinx.Graphics.Metal/Window.cs b/src/Ryujinx.Graphics.Metal/Window.cs index 65a47d217..29099e7b1 100644 --- a/src/Ryujinx.Graphics.Metal/Window.cs +++ b/src/Ryujinx.Graphics.Metal/Window.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Metal.Effects; +using Ryujinx.Graphics.Metal.SharpMetalExtensions; using SharpMetal.ObjectiveCCore; using SharpMetal.QuartzCore; using System; @@ -140,7 +141,15 @@ namespace Ryujinx.Graphics.Metal public void ChangeVSyncMode(VSyncMode vSyncMode) { - //_vSyncMode = vSyncMode; + switch (vSyncMode) + { + case VSyncMode.Unbounded: + _metalLayer.SetDisplaySyncEnabled(false); + break; + case VSyncMode.Switch: + _metalLayer.SetDisplaySyncEnabled(true); + break; + } } public void SetAntiAliasing(AntiAliasing effect) From d7b3dd12d14ef0409d9dd59328b9fcfcba8ab495 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Thu, 26 Dec 2024 22:58:49 -0600 Subject: [PATCH 02/14] UI: Set title bar icon to the already loaded one --- src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml | 3 +-- src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index 8207f8e03..2c07bd8ef 100644 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -17,8 +17,7 @@ Margin="7, 0" Height="25" Width="25" - ToolTip.Tip="{Binding Title}" - Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx_AntiAlias.png?assembly=Ryujinx.UI.Common" /> + ToolTip.Tip="{Binding Title}" /> Date: Thu, 26 Dec 2024 23:13:35 -0600 Subject: [PATCH 03/14] UI: Redirect IME errors to Debug instead of error --- src/Ryujinx/UI/Helpers/LoggerAdapter.cs | 10 +++++----- src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Ryujinx/UI/Helpers/LoggerAdapter.cs b/src/Ryujinx/UI/Helpers/LoggerAdapter.cs index 7982c17a6..2d26bd090 100644 --- a/src/Ryujinx/UI/Helpers/LoggerAdapter.cs +++ b/src/Ryujinx/UI/Helpers/LoggerAdapter.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Ava.UI.Helpers AvaLogger.Sink = new LoggerAdapter(); } - private static RyuLogger.Log? GetLog(AvaLogLevel level) + private static RyuLogger.Log? GetLog(AvaLogLevel level, string area) { return level switch { @@ -27,7 +27,7 @@ namespace Ryujinx.Ava.UI.Helpers AvaLogLevel.Debug => RyuLogger.Debug, AvaLogLevel.Information => RyuLogger.Debug, AvaLogLevel.Warning => RyuLogger.Debug, - AvaLogLevel.Error => RyuLogger.Error, + AvaLogLevel.Error => area is "IME" ? RyuLogger.Debug : RyuLogger.Error, AvaLogLevel.Fatal => RyuLogger.Error, _ => throw new ArgumentOutOfRangeException(nameof(level), level, null), }; @@ -35,17 +35,17 @@ namespace Ryujinx.Ava.UI.Helpers public bool IsEnabled(AvaLogLevel level, string area) { - return GetLog(level) != null; + return GetLog(level, area) != null; } public void Log(AvaLogLevel level, string area, object source, string messageTemplate) { - GetLog(level)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, null)); + GetLog(level, area)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, null)); } public void Log(AvaLogLevel level, string area, object source, string messageTemplate, params object[] propertyValues) { - GetLog(level)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, propertyValues)); + GetLog(level, area)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, propertyValues)); } private static string Format(AvaLogLevel level, string area, string template, object source, object[] v) diff --git a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml index 6871fd3f9..a0259c723 100644 --- a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml @@ -7,7 +7,6 @@ xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup" xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" - xmlns:local="clr-namespace:Ryujinx.Ava.UI.Views.Main" xmlns:config="clr-namespace:Ryujinx.Common.Configuration;assembly=Ryujinx.Common" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Ryujinx.Ava.UI.Views.Main.MainStatusBarView" From 9754d247b59a064f9888423ef6c227c6f209e784 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Thu, 26 Dec 2024 23:32:53 -0600 Subject: [PATCH 04/14] UI: Directly proxy window properties on the view model back to the stored window --- src/Ryujinx/RyujinxApp.axaml.cs | 7 +-- .../UI/ViewModels/MainWindowViewModel.cs | 45 +++++-------------- src/Ryujinx/UI/Windows/MainWindow.axaml | 5 --- 3 files changed, 14 insertions(+), 43 deletions(-) diff --git a/src/Ryujinx/RyujinxApp.axaml.cs b/src/Ryujinx/RyujinxApp.axaml.cs index bbef20aa0..c2f92f2f7 100644 --- a/src/Ryujinx/RyujinxApp.axaml.cs +++ b/src/Ryujinx/RyujinxApp.axaml.cs @@ -33,11 +33,8 @@ namespace Ryujinx.Ava .ApplicationLifetime.Cast() .MainWindow.Cast(); - public static bool IsClipboardAvailable(out IClipboard clipboard) - { - clipboard = MainWindow.Clipboard; - return clipboard != null; - } + public static bool IsClipboardAvailable(out IClipboard clipboard) + => (clipboard = MainWindow.Clipboard) != null; public static void SetTaskbarProgress(TaskBarProgressBarState state) => MainWindow.PlatformFeatures.SetTaskBarProgressBarState(state); public static void SetTaskbarProgressValue(ulong current, ulong total) => MainWindow.PlatformFeatures.SetTaskBarProgressBarValue(current, total); diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 04881b58d..d0ea64c37 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -109,13 +109,8 @@ namespace Ryujinx.Ava.UI.ViewModels private bool _areMimeTypesRegistered = FileAssociationHelper.AreMimeTypesRegistered; private bool _canUpdate = true; - private Cursor _cursor; - private string _title; private ApplicationData _currentApplicationData; private readonly AutoResetEvent _rendererWaitEvent; - private WindowState _windowState; - private double _windowWidth; - private double _windowHeight; private int _customVSyncInterval; private int _customVSyncIntervalPercentageProxy; @@ -216,7 +211,7 @@ namespace Ryujinx.Ava.UI.ViewModels public bool CanUpdate { - get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(false); + get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(); set { _canUpdate = value; @@ -226,12 +221,8 @@ namespace Ryujinx.Ava.UI.ViewModels public Cursor Cursor { - get => _cursor; - set - { - _cursor = value; - OnPropertyChanged(); - } + get => Window.Cursor; + set => Window.Cursor = value; } public ReadOnlyObservableCollection AppsObservableList @@ -813,35 +804,23 @@ namespace Ryujinx.Ava.UI.ViewModels public WindowState WindowState { - get => _windowState; + get => Window.WindowState; internal set { - _windowState = value; - - OnPropertyChanged(); + Window.WindowState = value; } } public double WindowWidth { - get => _windowWidth; - set - { - _windowWidth = value; - - OnPropertyChanged(); - } + get => Window.Width; + set => Window.Width = value; } public double WindowHeight { - get => _windowHeight; - set - { - _windowHeight = value; - - OnPropertyChanged(); - } + get => Window.Height; + set => Window.Height = value; } public bool IsGrid => Glyph == Glyph.Grid; @@ -889,11 +868,11 @@ namespace Ryujinx.Ava.UI.ViewModels public string Title { - get => _title; + get => Window.Title; set { - _title = value; - + Window.Title = value; + OnPropertyChanged(); } } diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml b/src/Ryujinx/UI/Windows/MainWindow.axaml index cb2e5936d..e3b6cf912 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml @@ -9,11 +9,6 @@ xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" xmlns:main="clr-namespace:Ryujinx.Ava.UI.Views.Main" - Cursor="{Binding Cursor}" - Title="{Binding Title}" - WindowState="{Binding WindowState}" - Width="{Binding WindowWidth}" - Height="{Binding WindowHeight}" MinWidth="800" MinHeight="500" d:DesignHeight="720" From c73b5bdf4604be24a6ae78c4aa5b5ae94ec0e6fa Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Thu, 26 Dec 2024 23:58:55 -0600 Subject: [PATCH 05/14] metal: wip: allow getting/setting developerHUDProperies --- .../CAMetalLayerExtensions.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs b/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs index 361419658..91e94fb2c 100644 --- a/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs +++ b/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs @@ -6,16 +6,25 @@ using System.Runtime.Versioning; namespace Ryujinx.Graphics.Metal.SharpMetalExtensions { - [SupportedOSPlatform("OSX")] + [SupportedOSPlatform("macOS")] public static class CAMetalLayerExtensions { private static readonly Selector sel_displaySyncEnabled = "displaySyncEnabled"; private static readonly Selector sel_setDisplaySyncEnabled = "setDisplaySyncEnabled:"; + private static readonly Selector sel_developerHUDProperties = "developerHUDProperties"; + private static readonly Selector sel_setDeveloperHUDProperties = "setDeveloperHUDProperties:"; + public static bool IsDisplaySyncEnabled(this CAMetalLayer metalLayer) => ObjectiveCRuntime.bool_objc_msgSend(metalLayer.NativePtr, sel_displaySyncEnabled); public static void SetDisplaySyncEnabled(this CAMetalLayer metalLayer, bool enabled) => ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDisplaySyncEnabled, enabled); + + public static nint GetDeveloperHudProperties(this CAMetalLayer metalLayer) + => ObjectiveCRuntime.IntPtr_objc_msgSend(metalLayer.NativePtr, sel_developerHUDProperties); + + public static void SetDeveloperHudProperties(this CAMetalLayer metalLayer, nint dictionaryPointer) + => ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDisplaySyncEnabled, dictionaryPointer); } } From 9df1366fa1d6c149e46148215cb32aad3fa48648 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 00:00:29 -0600 Subject: [PATCH 06/14] I may be stu-- nah. I am here. I am stupid for this one. --- .../CAMetalLayerExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs b/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs index 91e94fb2c..0d29a502b 100644 --- a/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs +++ b/src/Ryujinx.Graphics.Metal.SharpMetalExtensions/CAMetalLayerExtensions.cs @@ -25,6 +25,6 @@ namespace Ryujinx.Graphics.Metal.SharpMetalExtensions => ObjectiveCRuntime.IntPtr_objc_msgSend(metalLayer.NativePtr, sel_developerHUDProperties); public static void SetDeveloperHudProperties(this CAMetalLayer metalLayer, nint dictionaryPointer) - => ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDisplaySyncEnabled, dictionaryPointer); + => ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDeveloperHUDProperties, dictionaryPointer); } } From 0733b7d0a1bdfe4063af2c9d73528d03b62f02fe Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 00:38:12 -0600 Subject: [PATCH 07/14] chore: Remove duplicate VSyncMode enum in GAL --- src/Ryujinx.Graphics.GAL/IWindow.cs | 1 + .../Multithreading/ThreadedWindow.cs | 1 + src/Ryujinx.Graphics.GAL/VSyncMode.cs | 9 --------- src/Ryujinx.Graphics.Metal/Window.cs | 3 +++ src/Ryujinx.Graphics.OpenGL/Window.cs | 3 +++ src/Ryujinx.Graphics.Vulkan/Window.cs | 3 +++ src/Ryujinx.Graphics.Vulkan/WindowBase.cs | 3 +++ src/Ryujinx.HLE/HLEConfiguration.cs | 1 - .../HOS/Services/SurfaceFlinger/SurfaceFlinger.cs | 1 - 9 files changed, 14 insertions(+), 11 deletions(-) delete mode 100644 src/Ryujinx.Graphics.GAL/VSyncMode.cs diff --git a/src/Ryujinx.Graphics.GAL/IWindow.cs b/src/Ryujinx.Graphics.GAL/IWindow.cs index 12686cb28..48144f0b0 100644 --- a/src/Ryujinx.Graphics.GAL/IWindow.cs +++ b/src/Ryujinx.Graphics.GAL/IWindow.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Configuration; using System; namespace Ryujinx.Graphics.GAL diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs index 102fdb1bb..7a4836982 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedWindow.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Configuration; using Ryujinx.Graphics.GAL.Multithreading.Commands.Window; using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Resources; diff --git a/src/Ryujinx.Graphics.GAL/VSyncMode.cs b/src/Ryujinx.Graphics.GAL/VSyncMode.cs deleted file mode 100644 index c5794b8f7..000000000 --- a/src/Ryujinx.Graphics.GAL/VSyncMode.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.GAL -{ - public enum VSyncMode - { - Switch, - Unbounded, - Custom - } -} diff --git a/src/Ryujinx.Graphics.Metal/Window.cs b/src/Ryujinx.Graphics.Metal/Window.cs index 29099e7b1..203a29ebc 100644 --- a/src/Ryujinx.Graphics.Metal/Window.cs +++ b/src/Ryujinx.Graphics.Metal/Window.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Metal.Effects; @@ -6,6 +7,8 @@ using SharpMetal.ObjectiveCCore; using SharpMetal.QuartzCore; using System; using System.Runtime.Versioning; +using AntiAliasing = Ryujinx.Graphics.GAL.AntiAliasing; +using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter; namespace Ryujinx.Graphics.Metal { diff --git a/src/Ryujinx.Graphics.OpenGL/Window.cs b/src/Ryujinx.Graphics.OpenGL/Window.cs index 1dc8a51f6..8c35663ab 100644 --- a/src/Ryujinx.Graphics.OpenGL/Window.cs +++ b/src/Ryujinx.Graphics.OpenGL/Window.cs @@ -1,9 +1,12 @@ using OpenTK.Graphics.OpenGL; +using Ryujinx.Common.Configuration; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.OpenGL.Effects; using Ryujinx.Graphics.OpenGL.Effects.Smaa; using Ryujinx.Graphics.OpenGL.Image; using System; +using AntiAliasing = Ryujinx.Graphics.GAL.AntiAliasing; +using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter; namespace Ryujinx.Graphics.OpenGL { diff --git a/src/Ryujinx.Graphics.Vulkan/Window.cs b/src/Ryujinx.Graphics.Vulkan/Window.cs index 3e8d3b375..d135d0076 100644 --- a/src/Ryujinx.Graphics.Vulkan/Window.cs +++ b/src/Ryujinx.Graphics.Vulkan/Window.cs @@ -1,9 +1,12 @@ +using Ryujinx.Common.Configuration; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Vulkan.Effects; using Silk.NET.Vulkan; using Silk.NET.Vulkan.Extensions.KHR; using System; using System.Linq; +using AntiAliasing = Ryujinx.Graphics.GAL.AntiAliasing; +using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter; using VkFormat = Silk.NET.Vulkan.Format; namespace Ryujinx.Graphics.Vulkan diff --git a/src/Ryujinx.Graphics.Vulkan/WindowBase.cs b/src/Ryujinx.Graphics.Vulkan/WindowBase.cs index ca06ec0b8..807bb65e5 100644 --- a/src/Ryujinx.Graphics.Vulkan/WindowBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/WindowBase.cs @@ -1,5 +1,8 @@ +using Ryujinx.Common.Configuration; using Ryujinx.Graphics.GAL; using System; +using AntiAliasing = Ryujinx.Graphics.GAL.AntiAliasing; +using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter; namespace Ryujinx.Graphics.Vulkan { diff --git a/src/Ryujinx.HLE/HLEConfiguration.cs b/src/Ryujinx.HLE/HLEConfiguration.cs index f75ead588..52c2b3da4 100644 --- a/src/Ryujinx.HLE/HLEConfiguration.cs +++ b/src/Ryujinx.HLE/HLEConfiguration.cs @@ -9,7 +9,6 @@ using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.UI; using System; -using VSyncMode = Ryujinx.Common.Configuration.VSyncMode; namespace Ryujinx.HLE { diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index 23bf8bcfc..935e9895e 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -10,7 +10,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; -using VSyncMode = Ryujinx.Common.Configuration.VSyncMode; namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { From 1bc0159139cedcdcf2010d55adef97bad06f750f Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 00:41:50 -0600 Subject: [PATCH 08/14] Once again, I am stupid --- src/Ryujinx/AppHost.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index f976ecdf1..9a9c1d226 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -311,7 +311,7 @@ namespace Ryujinx.Ava Device.VSyncMode = e.NewValue; Device.UpdateVSyncInterval(); } - _renderer.Window?.ChangeVSyncMode((Ryujinx.Graphics.GAL.VSyncMode)e.NewValue); + _renderer.Window?.ChangeVSyncMode(e.NewValue); _viewModel.ShowCustomVSyncIntervalPicker = (e.NewValue == VSyncMode.Custom); } @@ -1074,7 +1074,7 @@ namespace Ryujinx.Ava Device.Gpu.SetGpuThread(); Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token); - _renderer.Window.ChangeVSyncMode((Ryujinx.Graphics.GAL.VSyncMode)Device.VSyncMode); + _renderer.Window.ChangeVSyncMode(Device.VSyncMode); while (_isActive) { From c69881a0a22104986a7141f40f8c4dd0e2963f09 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 00:47:57 -0600 Subject: [PATCH 09/14] UI: chore: remove direct static MainWindowViewModel reference --- src/Ryujinx/UI/Models/SaveModel.cs | 3 ++- src/Ryujinx/UI/ViewModels/SettingsViewModel.cs | 2 +- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 4 +--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx/UI/Models/SaveModel.cs b/src/Ryujinx/UI/Models/SaveModel.cs index cfc397c6e..578538d21 100644 --- a/src/Ryujinx/UI/Models/SaveModel.cs +++ b/src/Ryujinx/UI/Models/SaveModel.cs @@ -1,3 +1,4 @@ +using Gommon; using LibHac.Fs; using LibHac.Ncm; using Ryujinx.Ava.UI.ViewModels; @@ -47,7 +48,7 @@ namespace Ryujinx.Ava.UI.Models TitleId = info.ProgramId; UserId = info.UserId; - var appData = MainWindow.MainWindowViewModel.Applications.FirstOrDefault(x => x.IdString.Equals(TitleIdString, StringComparison.OrdinalIgnoreCase)); + var appData = RyujinxApp.MainWindow.ViewModel.Applications.FirstOrDefault(x => x.IdString.EqualsIgnoreCase(TitleIdString)); InGameList = appData != null; diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 7504147b2..9feaaba9b 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -750,7 +750,7 @@ namespace Ryujinx.Ava.UI.ViewModels config.ToFileFormat().SaveConfig(Program.ConfigurationPath); MainWindow.UpdateGraphicsConfig(); - MainWindow.MainWindowViewModel.VSyncModeSettingChanged(); + RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged(); SaveSettingsEvent?.Invoke(); diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index 660caa605..ca91b180f 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -39,8 +39,6 @@ namespace Ryujinx.Ava.UI.Windows { public partial class MainWindow : StyleableAppWindow { - internal static MainWindowViewModel MainWindowViewModel { get; private set; } - public MainWindowViewModel ViewModel { get; } internal readonly AvaHostUIHandler UiHandler; @@ -76,7 +74,7 @@ namespace Ryujinx.Ava.UI.Windows public MainWindow() { - DataContext = ViewModel = MainWindowViewModel = new MainWindowViewModel + DataContext = ViewModel = new MainWindowViewModel { Window = this }; From d3bc3a1081863d07fc8d4bdc48e6b69fafa5e41c Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 01:32:23 -0600 Subject: [PATCH 10/14] UI: Simplify LDN data logic --- src/Ryujinx.UI.Common/App/ApplicationData.cs | 2 ++ .../App/ApplicationLibrary.cs | 9 ++++--- src/Ryujinx.UI.Common/App/LdnGameDataList.cs | 24 +++++++++++++++++++ .../UI/ViewModels/MainWindowViewModel.cs | 6 +++-- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 18 ++++++++------ 5 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 src/Ryujinx.UI.Common/App/LdnGameDataList.cs diff --git a/src/Ryujinx.UI.Common/App/ApplicationData.cs b/src/Ryujinx.UI.Common/App/ApplicationData.cs index 657b9a022..ee5545dde 100644 --- a/src/Ryujinx.UI.Common/App/ApplicationData.cs +++ b/src/Ryujinx.UI.Common/App/ApplicationData.cs @@ -36,6 +36,8 @@ namespace Ryujinx.UI.App.Common public string Path { get; set; } public BlitStruct ControlHolder { get; set; } + public bool HasControlHolder => ControlHolder.ByteSpan.Length > 0; + public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed); public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed)?.Replace(" ", "\n") ?? LocalizedNever(); diff --git a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs index cb6467f5e..e78af3121 100644 --- a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs +++ b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs @@ -789,16 +789,15 @@ namespace Ryujinx.UI.App.Common using HttpClient httpClient = new HttpClient(); string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games"); ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData); - var evt = new LdnGameDataReceivedEventArgs + LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs { LdnData = ldnGameDataArray - }; - LdnGameDataReceived?.Invoke(null, evt); + }); } catch (Exception ex) { Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}"); - LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs() + LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs { LdnData = Array.Empty() }); @@ -806,7 +805,7 @@ namespace Ryujinx.UI.App.Common } else { - LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs() + LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs { LdnData = Array.Empty() }); diff --git a/src/Ryujinx.UI.Common/App/LdnGameDataList.cs b/src/Ryujinx.UI.Common/App/LdnGameDataList.cs new file mode 100644 index 000000000..d98fd081d --- /dev/null +++ b/src/Ryujinx.UI.Common/App/LdnGameDataList.cs @@ -0,0 +1,24 @@ +using LibHac.Ns; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Ryujinx.UI.App.Common +{ + public class LdnGameDataArray + { + private readonly LdnGameData[] _ldnDatas; + + public LdnGameDataArray(IEnumerable receivedData, ref ApplicationControlProperty acp) + { + LibHac.Common.FixedArrays.Array8 communicationId = acp.LocalCommunicationId; + + _ldnDatas = receivedData.Where(game => + communicationId.Items.Contains(Convert.ToUInt64(game.TitleId, 16)) + ).ToArray(); + } + + public int PlayerCount => _ldnDatas.Sum(it => it.PlayerCount); + public int GameCount => _ldnDatas.Length; + } +} diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index d0ea64c37..3b98a7aa3 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -9,6 +9,7 @@ using Avalonia.Threading; using DynamicData; using DynamicData.Binding; using FluentAvalonia.UI.Controls; +using Gommon; using LibHac.Common; using LibHac.Ns; using Ryujinx.Ava.Common; @@ -119,8 +120,9 @@ namespace Ryujinx.Ava.UI.ViewModels public ApplicationData ListSelectedApplication; public ApplicationData GridSelectedApplication; - - public IEnumerable LastLdnGameData; + + // Key is Title ID + public SafeDictionary LdnData = []; // The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions. // For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left. diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index ca91b180f..832674541 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -167,24 +167,28 @@ namespace Ryujinx.Ava.UI.Windows { Dispatcher.UIThread.Post(() => { - var ldnGameDataArray = e.LdnData; - ViewModel.LastLdnGameData = ldnGameDataArray; + var ldnGameDataArray = e.LdnData.ToList(); + ViewModel.LdnData.Clear(); foreach (var application in ViewModel.Applications) { + ViewModel.LdnData[application.IdString] = new LdnGameDataArray( + ldnGameDataArray, + ref application.ControlHolder.Value + ); + UpdateApplicationWithLdnData(application); } + ViewModel.RefreshView(); }); } private void UpdateApplicationWithLdnData(ApplicationData application) { - if (application.ControlHolder.ByteSpan.Length > 0 && ViewModel.LastLdnGameData != null) + if (application.HasControlHolder && ViewModel.LdnData.TryGetValue(application.IdString, out var ldnGameDatas)) { - IEnumerable ldnGameData = ViewModel.LastLdnGameData.Where(game => application.ControlHolder.Value.LocalCommunicationId.Items.Contains(Convert.ToUInt64(game.TitleId, 16))); - - application.PlayerCount = ldnGameData.Sum(game => game.PlayerCount); - application.GameCount = ldnGameData.Count(); + application.PlayerCount = ldnGameDatas.PlayerCount; + application.GameCount = ldnGameDatas.GameCount; } else { From 4c646721d6b57d462186f96de69b88de5f9f314e Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 01:38:51 -0600 Subject: [PATCH 11/14] infra: Testing moving canary to the future home of this fork --- .github/workflows/canary.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 3100671e9..cc57e7d5b 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -21,7 +21,7 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.2" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary" - RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "GreemDev" + RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Hydra-NX" RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx-Canary" RELEASE: 1 From 01c2e67334fc84ebc781c9413aa7f3f7a5203555 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 01:41:48 -0600 Subject: [PATCH 12/14] lol --- .github/workflows/canary.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index cc57e7d5b..03247ff6d 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -23,7 +23,7 @@ env: RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary" RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Hydra-NX" RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx" - RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx-Canary" + RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Canary-Releases" RELEASE: 1 jobs: From ccddaa77d1dd422dd8f09dc8f89ab5e4704f8b30 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 01:59:29 -0600 Subject: [PATCH 13/14] infra: Org --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 59c31c71b..825a23ae6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.2" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" - RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "GreemDev" + RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Hydra-NX" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx" RELEASE: 1 From 9eb273a0f754ac50de1485e3d5782652993af647 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 27 Dec 2024 02:05:37 -0600 Subject: [PATCH 14/14] Org rename (they call me indecisive) --- .github/workflows/canary.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 03247ff6d..ffbf1ebf7 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -21,7 +21,7 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.2" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary" - RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Hydra-NX" + RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Canary-Releases" RELEASE: 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 825a23ae6..066b978c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.2" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" - RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Hydra-NX" + RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx" RELEASE: 1