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
This commit is contained in:
Evan Husted 2024-10-24 14:14:12 -05:00
parent 7618ef134d
commit a01a06cd3f
10 changed files with 101 additions and 36 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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();

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -11,7 +11,9 @@ namespace Ryujinx.Ava.UI.Models
public string FifoStatus { get; }
public string GameStatus { get; }
public StatusUpdatedEventArgs(bool vSyncEnabled, string volumeStatus, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus)
public uint ShaderCount { get; }
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;
}
}
}

View File

@ -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;
@ -507,6 +521,16 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public string ShaderCountText
{
get => _shaderCountText;
set
{
_shaderCountText = value;
OnPropertyChanged();
}
}
public string BackendText
{
get => _backendText;
@ -1188,7 +1212,6 @@ namespace Ryujinx.Ava.UI.ViewModels
{
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;
});

View File

@ -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();

View File

@ -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"