aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ARMeilleure/Translation/PTC/Ptc.cs13
-rw-r--r--Ryujinx.Graphics.Gpu/GpuContext.cs20
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs40
-rw-r--r--Ryujinx/Ui/MainWindow.cs52
-rw-r--r--Ryujinx/Ui/MainWindow.glade42
5 files changed, 148 insertions, 19 deletions
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index 266bdba6..c931aaea 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -70,6 +70,10 @@ namespace ARMeilleure.Translation.PTC
internal static PtcState State { get; private set; }
+ // Progress update events
+ public static event Action<bool> PtcTranslationStateChanged;
+ public static event Action<int, int> PtcTranslationProgressChanged;
+
static Ptc()
{
InitializeMemoryStreams();
@@ -772,6 +776,8 @@ namespace ARMeilleure.Translation.PTC
ThreadPool.QueueUserWorkItem(TranslationLogger, profiledFuncsToTranslate.Count);
+ PtcTranslationStateChanged?.Invoke(true);
+
void TranslateFuncs()
{
while (profiledFuncsToTranslate.TryDequeue(out var item))
@@ -820,6 +826,7 @@ namespace ARMeilleure.Translation.PTC
threads.Clear();
_loggerEvent.Set();
+ PtcTranslationStateChanged?.Invoke(false);
PtcJumpTable.Initialize(jumpTable);
@@ -833,15 +840,15 @@ namespace ARMeilleure.Translation.PTC
private static void TranslationLogger(object state)
{
- const int refreshRate = 1; // Seconds.
+ const int refreshRate = 100; // ms
int profiledFuncsToTranslateCount = (int)state;
do
{
- Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {profiledFuncsToTranslateCount} functions translated");
+ PtcTranslationProgressChanged?.Invoke(_translateCount, profiledFuncsToTranslateCount);
}
- while (!_loggerEvent.WaitOne(refreshRate * 1000));
+ while (!_loggerEvent.WaitOne(refreshRate));
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {profiledFuncsToTranslateCount} functions translated");
}
diff --git a/Ryujinx.Graphics.Gpu/GpuContext.cs b/Ryujinx.Graphics.Gpu/GpuContext.cs
index 15f757c8..06be6e05 100644
--- a/Ryujinx.Graphics.Gpu/GpuContext.cs
+++ b/Ryujinx.Graphics.Gpu/GpuContext.cs
@@ -80,6 +80,26 @@ namespace Ryujinx.Graphics.Gpu
internal Capabilities Capabilities => _caps.Value;
/// <summary>
+ /// Signaled when shader cache begins and ends loading.
+ /// Signals true when loading has started, false when ended.
+ /// </summary>
+ public event Action<bool> ShaderCacheStateChanged
+ {
+ add => Methods.ShaderCache.ShaderCacheStateChanged += value;
+ remove => Methods.ShaderCache.ShaderCacheStateChanged -= value;
+ }
+
+ /// <summary>
+ /// Signaled while shader cache is loading to indicate current progress.
+ /// Provides current and total number of shaders loaded.
+ /// </summary>
+ public event Action<int, int> ShaderCacheProgressChanged
+ {
+ add => Methods.ShaderCache.ShaderCacheProgressChanged += value;
+ remove => Methods.ShaderCache.ShaderCacheProgressChanged -= value;
+ }
+
+ /// <summary>
/// Creates a new instance of the GPU emulation context.
/// </summary>
/// <param name="renderer">Host renderer</param>
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 6a3971df..bf89f29d 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -9,6 +9,7 @@ using Ryujinx.Graphics.Shader.Translation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Threading;
namespace Ryujinx.Graphics.Gpu.Shader
{
@@ -36,6 +37,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
private const ulong ShaderCodeGenVersion = 1961;
+ // Progress reporting helpers
+ private int _shaderCount;
+ private readonly AutoResetEvent _progressReportEvent;
+ public event Action<bool> ShaderCacheStateChanged;
+ public event Action<int, int> ShaderCacheProgressChanged;
+
/// <summary>
/// Creates a new instance of the shader cache.
/// </summary>
@@ -50,6 +57,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
_gpPrograms = new Dictionary<ShaderAddresses, List<ShaderBundle>>();
_gpProgramsDiskCache = new Dictionary<Hash128, ShaderBundle>();
_cpProgramsDiskCache = new Dictionary<Hash128, ShaderBundle>();
+
+ _progressReportEvent = new AutoResetEvent(false);
}
/// <summary>
@@ -76,12 +85,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
ReadOnlySpan<Hash128> guestProgramList = _cacheManager.GetGuestProgramList();
+ _progressReportEvent.Reset();
+ _shaderCount = 0;
+
+ ShaderCacheStateChanged?.Invoke(true);
+ ThreadPool.QueueUserWorkItem(ProgressLogger, guestProgramList.Length);
+
for (int programIndex = 0; programIndex < guestProgramList.Length; programIndex++)
{
Hash128 key = guestProgramList[programIndex];
- Logger.Info?.Print(LogClass.Gpu, $"Compiling shader {key} ({programIndex + 1} / {guestProgramList.Length})");
-
byte[] hostProgramBinary = _cacheManager.GetHostProgramByHash(ref key);
bool hasHostCache = hostProgramBinary != null;
@@ -304,6 +317,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
_gpProgramsDiskCache.Add(key, new ShaderBundle(hostProgram, shaders));
}
+
+ _shaderCount = programIndex;
}
if (!isReadOnly)
@@ -314,8 +329,26 @@ namespace Ryujinx.Graphics.Gpu.Shader
_cacheManager.Synchronize();
}
- Logger.Info?.Print(LogClass.Gpu, "Shader cache loaded.");
+ _progressReportEvent.Set();
+ ShaderCacheStateChanged?.Invoke(false);
+
+ Logger.Info?.Print(LogClass.Gpu, $"Shader cache loaded {_shaderCount} entries.");
+ }
+ }
+
+ /// <summary>
+ /// Raises ShaderCacheProgressChanged events periodically.
+ /// </summary>
+ private void ProgressLogger(object state)
+ {
+ const int refreshRate = 100; // ms
+
+ int totalCount = (int)state;
+ do
+ {
+ ShaderCacheProgressChanged?.Invoke(_shaderCount, totalCount);
}
+ while (!_progressReportEvent.WaitOne(refreshRate));
}
/// <summary>
@@ -787,6 +820,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
}
+ _progressReportEvent?.Dispose();
_cacheManager?.Dispose();
}
}
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index 809b693b..7d48422c 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -92,10 +92,14 @@ namespace Ryujinx.Ui
[GUI] Label _gpuName;
[GUI] Label _progressLabel;
[GUI] Label _firmwareVersionLabel;
- [GUI] LevelBar _progressBar;
+ [GUI] ProgressBar _progressBar;
[GUI] Box _viewBox;
[GUI] Label _vSyncStatus;
[GUI] Box _listStatusBox;
+ [GUI] Label _loadingStatusLabel;
+ [GUI] ProgressBar _loadingStatusBar;
+
+ private string _loadingStatusTitle = "";
#pragma warning restore CS0649, IDE0044, CS0169
@@ -333,6 +337,48 @@ namespace Ryujinx.Ui
_emulationContext.Initialize();
}
+ private void SetupProgressUiHandlers()
+ {
+ Ptc.PtcTranslationStateChanged -= PtcStatusChanged;
+ Ptc.PtcTranslationStateChanged += PtcStatusChanged;
+
+ Ptc.PtcTranslationProgressChanged -= LoadingProgressChanged;
+ Ptc.PtcTranslationProgressChanged += LoadingProgressChanged;
+
+ _emulationContext.Gpu.ShaderCacheStateChanged -= ShaderCacheStatusChanged;
+ _emulationContext.Gpu.ShaderCacheStateChanged += ShaderCacheStatusChanged;
+
+ _emulationContext.Gpu.ShaderCacheProgressChanged -= LoadingProgressChanged;
+ _emulationContext.Gpu.ShaderCacheProgressChanged += LoadingProgressChanged;
+ }
+
+ private void ShaderCacheStatusChanged(bool state)
+ {
+ _loadingStatusTitle = "Shaders";
+ Application.Invoke(delegate
+ {
+ _loadingStatusBar.Visible = _loadingStatusLabel.Visible = state;
+ });
+ }
+
+ private void PtcStatusChanged(bool state)
+ {
+ _loadingStatusTitle = "PTC";
+ Application.Invoke(delegate
+ {
+ _loadingStatusBar.Visible = _loadingStatusLabel.Visible = state;
+ });
+ }
+
+ private void LoadingProgressChanged(int value, int total)
+ {
+ Application.Invoke(delegate
+ {
+ _loadingStatusBar.Fraction = (double)value / total;
+ _loadingStatusLabel.Text = $"{_loadingStatusTitle} : {value}/{total}";
+ });
+ }
+
public void UpdateGameTable()
{
if (_updatingGameTable || _gameLoaded)
@@ -531,6 +577,8 @@ namespace Ryujinx.Ui
_deviceExitStatus.Reset();
+ SetupProgressUiHandlers();
+
Translator.IsReadyForTranslation.Reset();
#if MACOS_BUILD
CreateGameWindow();
@@ -775,7 +823,7 @@ namespace Ryujinx.Ui
barValue = (float)args.NumAppsLoaded / args.NumAppsFound;
}
- _progressBar.Value = barValue;
+ _progressBar.Fraction = barValue;
// Reset the vertical scrollbar to the top when titles finish loading
if (args.NumAppsLoaded == args.NumAppsFound)
diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade
index 688f0e25..5558403b 100644
--- a/Ryujinx/Ui/MainWindow.glade
+++ b/Ryujinx/Ui/MainWindow.glade
@@ -459,13 +459,14 @@
</packing>
</child>
<child>
- <object class="GtkLevelBar" id="_progressBar">
+ <object class="GtkProgressBar" id="_progressBar">
<property name="width_request">200</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="margin_right">5</property>
+ <property name="margin_bottom">6</property>
</object>
<packing>
<property name="expand">True</property>
@@ -640,6 +641,7 @@
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">5</property>
+ <property name="margin_right">5</property>
</object>
<packing>
<property name="expand">True</property>
@@ -654,16 +656,34 @@
<property name="position">1</property>
</packing>
</child>
- <child>
- <object class="GtkSeparator">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">3</property>
- </packing>
+ <child>
+ <object class="GtkLabel" id="_loadingStatusLabel">
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="label" translatable="yes">0/0 </property>
+ <property name="visible">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkProgressBar" id="_loadingStatusBar">
+ <property name="width_request">200</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="margin_bottom">6</property>
+ <property name="visible">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">12</property>
+ </packing>
</child>
<child>
<object class="GtkBox">