diff --git a/src/Ryujinx.Graphics.GAL/IRenderer.cs b/src/Ryujinx.Graphics.GAL/IRenderer.cs index 85d0bd729f..c2fdcbe4bd 100644 --- a/src/Ryujinx.Graphics.GAL/IRenderer.cs +++ b/src/Ryujinx.Graphics.GAL/IRenderer.cs @@ -14,6 +14,8 @@ namespace Ryujinx.Graphics.GAL IWindow Window { get; } + uint ProgramCount { get; } + void BackgroundContextAction(Action action, bool alwaysBackground = false); BufferHandle CreateBuffer(int size, BufferAccess access = BufferAccess.Default); diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs index cc3d2e5c11..0bd3dc592b 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs +++ b/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().Set(Ref((IProgramRequest)request)); QueueCommand(); diff --git a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index ba9cd45c67..502c1a929a 100644 --- a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs +++ b/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 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); } diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 33e41ab489..09c5a3b9cc 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/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) diff --git a/src/Ryujinx.Gtk3/UI/StatusUpdatedEventArgs.cs b/src/Ryujinx.Gtk3/UI/StatusUpdatedEventArgs.cs index db467ebfca..8ff461cf83 100644 --- a/src/Ryujinx.Gtk3/UI/StatusUpdatedEventArgs.cs +++ b/src/Ryujinx.Gtk3/UI/StatusUpdatedEventArgs.cs @@ -13,7 +13,15 @@ namespace Ryujinx.UI public string GpuName; public string GpuBackend; - public StatusUpdatedEventArgs(bool vSyncEnabled, float volume, string gpuBackend, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, string gpuName) + public StatusUpdatedEventArgs( + bool vSyncEnabled, + float volume, + string gpuBackend, + string dockedMode, + string aspectRatio, + string gameStatus, + string fifoStatus, + string gpuName) { VSyncEnabled = vSyncEnabled; Volume = volume; diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index 0db8ef4143..1c2922186a 100644 --- a/src/Ryujinx/AppHost.cs +++ b/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; @@ -1059,6 +1063,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)"; @@ -1070,7 +1076,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() @@ -1096,6 +1103,25 @@ 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) diff --git a/src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs b/src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs index ee5648faf8..744c96abe3 100644 --- a/src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs +++ b/src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs @@ -10,8 +10,9 @@ 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 +20,7 @@ namespace Ryujinx.Ava.UI.Models AspectRatio = aspectRatio; GameStatus = gameStatus; FifoStatus = fifoStatus; + ShaderCount = shaderCount; } } } diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index bd9f165b92..ab6338e845 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -62,6 +62,7 @@ namespace Ryujinx.Ava.UI.ViewModels private string _gameStatusText; private string _volumeStatusText; private string _gpuStatusText; + private string _shaderCountText; private bool _isAmiiboRequested; private bool _isGameRunning; private bool _isFullScreen; @@ -502,6 +503,17 @@ namespace Ryujinx.Ava.UI.ViewModels } } + public string ShaderCountText + { + get => _shaderCountText; + set + { + _shaderCountText = value; + + OnPropertyChanged(); + } + } + public string BackendText { get => _backendText; @@ -1243,6 +1255,7 @@ namespace Ryujinx.Ava.UI.ViewModels GameStatusText = args.GameStatus; VolumeStatusText = args.VolumeStatus; FifoStatusText = args.FifoStatus; + ShaderCountText = args.ShaderCount > 0 ? LocaleManager.Instance[LocaleKeys.CompilingShaders] + $": {args.ShaderCount}" : ""; ShowStatusSeparator = true; }); diff --git a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml index f9e192e620..08301b96fc 100644 --- a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml @@ -270,8 +270,21 @@ VerticalAlignment="Center" IsVisible="{Binding !ShowLoadProgress}" Text="{Binding GpuNameText}" - TextAlignment="Start" /> - + TextAlignment="Left" /> + + +