ソースを参照

2 unmerged PRs from original Ryujinx:
Implement shader compile counter (currently not translated, will change, need to pull changes.)
Remove event logic in favor of a single init function.
Thanks @MutantAura

Evan Husted 1 年間 前
コミット
a01a06cd3f

+ 6 - 4
src/Ryujinx.Common/ReactiveObject.cs

@@ -41,10 +41,12 @@ namespace Ryujinx.Common
             }
         }
 
-        public static implicit operator T(ReactiveObject<T> obj)
-        {
-            return obj.Value;
-        }
+        public static implicit operator T(ReactiveObject<T> obj) => obj.Value;
+    }
+
+    public static class ReactiveObjectHelper
+    {
+        public static void Toggle(this ReactiveObject<bool> rBoolean) => rBoolean.Value = !rBoolean.Value;
     }
 
     public class ReactiveEventArgs<T>(T oldValue, T newValue)

+ 2 - 0
src/Ryujinx.Graphics.GAL/IRenderer.cs

@@ -13,6 +13,8 @@ namespace Ryujinx.Graphics.GAL
         IPipeline Pipeline { get; }
 
         IWindow Window { get; }
+        
+        uint ProgramCount { get; }
 
         void BackgroundContextAction(Action action, bool alwaysBackground = false);
 

+ 4 - 0
src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs

@@ -55,6 +55,8 @@ namespace Ryujinx.Graphics.GAL.Multithreading
         private int _refProducerPtr;
         private int _refConsumerPtr;
 
+        public uint ProgramCount { get; set; } = 0;
+
         private Action _interruptAction;
         private readonly object _interruptLock = new();
 
@@ -307,6 +309,8 @@ namespace Ryujinx.Graphics.GAL.Multithreading
 
             Programs.Add(request);
 
+            ProgramCount++;
+
             New<CreateProgramCommand>().Set(Ref((IProgramRequest)request));
             QueueCommand();
 

+ 4 - 0
src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs

@@ -29,6 +29,8 @@ namespace Ryujinx.Graphics.OpenGL
 
         private readonly Sync _sync;
 
+        public uint ProgramCount { get; set; } = 0;
+
         public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
 
         internal PersistentBuffers PersistentBuffers { get; }
@@ -94,6 +96,8 @@ namespace Ryujinx.Graphics.OpenGL
 
         public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
         {
+            ProgramCount++;
+            
             return new Program(shaders, info.FragmentOutputMap);
         }
 

+ 4 - 0
src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs

@@ -27,6 +27,8 @@ namespace Ryujinx.Graphics.Vulkan
 
         private bool _initialized;
 
+        public uint ProgramCount { get; set; } = 0;
+
         internal FormatCapabilities FormatCapabilities { get; private set; }
         internal HardwareCapabilities Capabilities;
 
@@ -544,6 +546,8 @@ namespace Ryujinx.Graphics.Vulkan
 
         public IProgram CreateProgram(ShaderSource[] sources, ShaderInfo info)
         {
+            ProgramCount++;
+            
             bool isCompute = sources.Length == 1 && sources[0].Stage == ShaderStage.Compute;
 
             if (info.State.HasValue || isCompute)

+ 35 - 12
src/Ryujinx/AppHost.cs

@@ -103,6 +103,10 @@ namespace Ryujinx.Ava
         private CursorStates _cursorState = !ConfigurationState.Instance.Hid.EnableMouse.Value ?
             CursorStates.CursorIsVisible : CursorStates.CursorIsHidden;
 
+        private DateTime _lastShaderReset;
+        private uint _displayCount;
+        private uint _previousCount = 0;
+
         private bool _isStopped;
         private bool _isActive;
         private bool _renderingStarted;
@@ -120,7 +124,6 @@ namespace Ryujinx.Ava
         private readonly object _lockObject = new();
 
         public event EventHandler AppExit;
-        public event EventHandler<StatusInitEventArgs> StatusInitEvent;
         public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
 
         public VirtualFileSystem VirtualFileSystem { get; }
@@ -511,8 +514,7 @@ namespace Ryujinx.Ava
             }
 
             _isStopped = true;
-            _isActive = false;
-            DiscordIntegrationModule.SwitchToMainState();
+            Stop();
         }
 
         public void DisposeContext()
@@ -1043,14 +1045,14 @@ namespace Ryujinx.Ava
 
         public void InitStatus()
         {
-            StatusInitEvent?.Invoke(this, new StatusInitEventArgs(
-                ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
-                {
-                    GraphicsBackend.Vulkan => "Vulkan",
-                    GraphicsBackend.OpenGl => "OpenGL",
-                    _ => throw new NotImplementedException()
-                },
-                $"GPU: {_renderer.GetHardwareInfo().GpuDriver}"));
+            _viewModel.BackendText = ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
+            {
+                GraphicsBackend.Vulkan => "Vulkan",
+                GraphicsBackend.OpenGl => "OpenGL",
+                _ => throw new NotImplementedException()
+            };
+
+            _viewModel.GpuNameText = $"GPU: {_renderer.GetHardwareInfo().GpuDriver}";
         }
 
         public void UpdateStatus()
@@ -1058,6 +1060,8 @@ namespace Ryujinx.Ava
             // Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued.
             string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld];
 
+            UpdateShaderCount();
+            
             if (GraphicsConfig.ResScale != 1)
             {
                 dockedMode += $" ({GraphicsConfig.ResScale}x)";
@@ -1069,7 +1073,8 @@ namespace Ryujinx.Ava
                 dockedMode,
                 ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
                 LocaleManager.Instance[LocaleKeys.Game] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
-                $"FIFO: {Device.Statistics.GetFifoPercent():00.00} %"));
+                $"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
+                _displayCount));
         }
 
         public async Task ShowExitPrompt()
@@ -1095,6 +1100,24 @@ namespace Ryujinx.Ava
             }
         }
 
+        private void UpdateShaderCount()
+        {
+            // If there is a mismatch between total program compile and previous count
+            // this means new shaders have been compiled and should be displayed.
+            if (_renderer.ProgramCount != _previousCount)
+            {
+                _displayCount += _renderer.ProgramCount - _previousCount;
+                _lastShaderReset = DateTime.Now;
+                _previousCount = _renderer.ProgramCount;
+            }
+            // Check if 5s has passed since any new shaders were compiled.
+            // If yes, reset the counter.
+            else if (_lastShaderReset.AddSeconds(5) <= DateTime.Now)
+            {
+                _displayCount = 0;
+            }
+        }
+
         private bool UpdateFrame()
         {
             if (!_isActive)

+ 4 - 1
src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs

@@ -10,8 +10,10 @@ namespace Ryujinx.Ava.UI.Models
         public string DockedMode { get; }
         public string FifoStatus { get; }
         public string GameStatus { get; }
+        
+        public uint ShaderCount { get; }
 
-        public StatusUpdatedEventArgs(bool vSyncEnabled, string volumeStatus, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus)
+        public StatusUpdatedEventArgs(bool vSyncEnabled, string volumeStatus, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, uint shaderCount)
         {
             VSyncEnabled = vSyncEnabled;
             VolumeStatus = volumeStatus;
@@ -19,6 +21,7 @@ namespace Ryujinx.Ava.UI.Models
             AspectRatio = aspectRatio;
             GameStatus = gameStatus;
             FifoStatus = fifoStatus;
+            ShaderCount = shaderCount;
         }
     }
 }

+ 27 - 14
src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs

@@ -8,6 +8,7 @@ using Avalonia.Threading;
 using DynamicData;
 using DynamicData.Binding;
 using FluentAvalonia.UI.Controls;
+using Gommon;
 using LibHac.Common;
 using Ryujinx.Ava.Common;
 using Ryujinx.Ava.Common.Locale;
@@ -64,7 +65,9 @@ namespace Ryujinx.Ava.UI.ViewModels
         private string _gameStatusText;
         private string _volumeStatusText;
         private string _gpuStatusText;
+        private string _shaderCountText;
         private bool _isAmiiboRequested;
+        private bool _showRightmostSeparator;
         private bool _isGameRunning;
         private bool _isFullScreen;
         private int _progressMaximum;
@@ -256,6 +259,17 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public bool ShowFirmwareStatus => !ShowLoadProgress;
 
+        public bool ShowRightmostSeparator 
+        {
+            get => _showRightmostSeparator;
+            set
+            {
+                _showRightmostSeparator = value;
+
+                OnPropertyChanged();
+            }
+        }
+
         public bool IsGameRunning
         {
             get => _isGameRunning;
@@ -506,6 +520,16 @@ namespace Ryujinx.Ava.UI.ViewModels
                 OnPropertyChanged();
             }
         }
+        
+        public string ShaderCountText
+        {
+            get => _shaderCountText;
+            set
+            {
+                _shaderCountText = value;
+                OnPropertyChanged();
+            }
+        }
 
         public string BackendText
         {
@@ -1187,8 +1211,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         private void InitializeGame()
         {
             RendererHostControl.WindowCreated += RendererHost_Created;
-
-            AppHost.StatusInitEvent += Init_StatusBar;
+            
             AppHost.StatusUpdatedEvent += Update_StatusBar;
             AppHost.AppExit += AppHost_AppExit;
 
@@ -1215,18 +1238,6 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        private void Init_StatusBar(object sender, StatusInitEventArgs args)
-        {
-            if (ShowMenuAndStatusBar && !ShowLoadProgress)
-            {
-                Dispatcher.UIThread.InvokeAsync(() =>
-                {
-                    GpuNameText = args.GpuName;
-                    BackendText = args.GpuBackend;
-                });
-            }
-        }
-
         private void Update_StatusBar(object sender, StatusUpdatedEventArgs args)
         {
             if (ShowMenuAndStatusBar && !ShowLoadProgress)
@@ -1249,6 +1260,8 @@ namespace Ryujinx.Ava.UI.ViewModels
                     GameStatusText = args.GameStatus;
                     VolumeStatusText = args.VolumeStatus;
                     FifoStatusText = args.FifoStatus;
+                    ShaderCountText = args.ShaderCount > 0 ? $"Compiling shaders: {args.ShaderCount}" : string.Empty;
+                    ShowRightmostSeparator = !ShaderCountText.IsNullOrEmpty();
 
                     ShowStatusSeparator = true;
                 });

+ 2 - 5
src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs

@@ -4,6 +4,7 @@ using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Platform.Storage;
 using Avalonia.Threading;
 using DynamicData;
+using Gommon;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Models;
@@ -313,11 +314,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public void DeleteAll()
         {
-            foreach (var mod in Mods)
-            {
-                Delete(mod);
-            }
-
+            Mods.ForEach(Delete);
             Mods.Clear();
             OnPropertyChanged(nameof(ModCount));
             Sort();

+ 13 - 0
src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml

@@ -261,6 +261,19 @@
                 IsVisible="{Binding !ShowLoadProgress}"
                 Text="{Binding GpuNameText}"
                 TextAlignment="Start" />
+            <Border
+                Width="2"
+                Height="12"
+                Margin="0"
+                BorderBrush="Gray"
+                BorderThickness="1"
+                IsVisible="{Binding ShowRightmostSeparator}" />
+            <TextBlock
+                Name="ShaderCount"
+                Margin="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                Text="{Binding ShaderCountText}" />
         </StackPanel>
         <StackPanel
             Grid.Column="3"