Salieri: shader cache (#1701)
Here come Salieri, my implementation of a disk shader cache! "I'm sure you know why I named it that." "It doesn't really mean anything." This implementation collects shaders at runtime and cache them to be later compiled when starting a game.
This commit is contained in:
parent
7166e82c3c
commit
48f6570557
57 changed files with 3589 additions and 396 deletions
|
@ -21,6 +21,7 @@
|
|||
"enable_discord_integration": true,
|
||||
"check_updates_on_start": true,
|
||||
"enable_vsync": true,
|
||||
"enable_shader_cache": true,
|
||||
"enable_multicore_scheduling": true,
|
||||
"enable_ptc": false,
|
||||
"enable_fs_integrity_checks": true,
|
||||
|
|
|
@ -199,19 +199,6 @@ namespace Ryujinx.Ui
|
|||
Gtk.Application.Invoke(delegate
|
||||
{
|
||||
parent.Present();
|
||||
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(_device.Application.TitleName) ? string.Empty
|
||||
: $" - {_device.Application.TitleName}";
|
||||
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(_device.Application.DisplayVersion) ? string.Empty
|
||||
: $" v{_device.Application.DisplayVersion}";
|
||||
|
||||
string titleIdSection = string.IsNullOrWhiteSpace(_device.Application.TitleIdText) ? string.Empty
|
||||
: $" ({_device.Application.TitleIdText.ToUpper()})";
|
||||
|
||||
string titleArchSection = _device.Application.TitleIs64Bit ? " (64-bit)" : " (32-bit)";
|
||||
|
||||
parent.Title = $"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
|
||||
});
|
||||
|
||||
Thread renderLoopThread = new Thread(Render)
|
||||
|
@ -313,7 +300,7 @@ namespace Ryujinx.Ui
|
|||
{
|
||||
if (!(_device.Gpu.Renderer is Renderer))
|
||||
{
|
||||
throw new NotSupportedException($"GPU renderer must be an OpenGL renderer when using GLRenderer!");
|
||||
throw new NotSupportedException($"GPU renderer must be an OpenGL renderer when using {typeof(Renderer).Name}!");
|
||||
}
|
||||
|
||||
_renderer = (Renderer)_device.Gpu.Renderer;
|
||||
|
@ -327,7 +314,7 @@ namespace Ryujinx.Ui
|
|||
parent.Present();
|
||||
GraphicsContext.MakeCurrent(WindowInfo);
|
||||
|
||||
_renderer.Initialize(_glLogLevel);
|
||||
_device.Gpu.Initialize(_glLogLevel);
|
||||
|
||||
// Make sure the first frame is not transparent.
|
||||
GL.ClearColor(OpenTK.Color.Black);
|
||||
|
|
|
@ -111,22 +111,34 @@ namespace Ryujinx.Ui
|
|||
|
||||
MenuItem managePtcMenu = new MenuItem("Cache Management");
|
||||
|
||||
MenuItem purgePtcCache = new MenuItem("Purge PPTC cache")
|
||||
MenuItem purgePtcCache = new MenuItem("Purge PPTC Cache")
|
||||
{
|
||||
TooltipText = "Delete the Application's PPTC cache."
|
||||
};
|
||||
|
||||
MenuItem openPtcDir = new MenuItem("Open PPTC directory")
|
||||
|
||||
MenuItem purgeShaderCache = new MenuItem("Purge Shader Cache")
|
||||
{
|
||||
TooltipText = "Open the directory which contains Application's PPTC cache."
|
||||
TooltipText = "Delete the Application's shader cache."
|
||||
};
|
||||
|
||||
MenuItem openPtcDir = new MenuItem("Open PPTC Directory")
|
||||
{
|
||||
TooltipText = "Open the directory which contains the Application's PPTC cache."
|
||||
};
|
||||
|
||||
MenuItem openShaderCacheDir = new MenuItem("Open Shader Cache Directory")
|
||||
{
|
||||
TooltipText = "Open the directory which contains the Application's shader cache."
|
||||
};
|
||||
|
||||
Menu manageSubMenu = new Menu();
|
||||
|
||||
Menu managePtcSubMenu = new Menu();
|
||||
manageSubMenu.Append(purgePtcCache);
|
||||
manageSubMenu.Append(purgeShaderCache);
|
||||
manageSubMenu.Append(openPtcDir);
|
||||
manageSubMenu.Append(openShaderCacheDir);
|
||||
|
||||
managePtcSubMenu.Append(purgePtcCache);
|
||||
managePtcSubMenu.Append(openPtcDir);
|
||||
|
||||
managePtcMenu.Submenu = managePtcSubMenu;
|
||||
managePtcMenu.Submenu = manageSubMenu;
|
||||
|
||||
openSaveUserDir.Activated += OpenSaveUserDir_Clicked;
|
||||
openSaveDeviceDir.Activated += OpenSaveDeviceDir_Clicked;
|
||||
|
@ -138,8 +150,10 @@ namespace Ryujinx.Ui
|
|||
extractExeFs.Activated += ExtractExeFs_Clicked;
|
||||
extractLogo.Activated += ExtractLogo_Clicked;
|
||||
purgePtcCache.Activated += PurgePtcCache_Clicked;
|
||||
purgeShaderCache.Activated += PurgeShaderCache_Clicked;
|
||||
openPtcDir.Activated += OpenPtcDir_Clicked;
|
||||
|
||||
openShaderCacheDir.Activated += OpenShaderCacheDir_Clicked;
|
||||
|
||||
this.Add(openSaveUserDir);
|
||||
this.Add(openSaveDeviceDir);
|
||||
this.Add(openSaveBcatDir);
|
||||
|
@ -640,6 +654,24 @@ namespace Ryujinx.Ui
|
|||
Verb = "open"
|
||||
});
|
||||
}
|
||||
|
||||
private void OpenShaderCacheDir_Clicked(object sender, EventArgs args)
|
||||
{
|
||||
string titleId = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n")[1].ToLower();
|
||||
string shaderCacheDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, titleId, "cache", "shader");
|
||||
|
||||
if (!Directory.Exists(shaderCacheDir))
|
||||
{
|
||||
Directory.CreateDirectory(shaderCacheDir);
|
||||
}
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = shaderCacheDir,
|
||||
UseShellExecute = true,
|
||||
Verb = "open"
|
||||
});
|
||||
}
|
||||
|
||||
private void PurgePtcCache_Clicked(object sender, EventArgs args)
|
||||
{
|
||||
|
@ -678,5 +710,41 @@ namespace Ryujinx.Ui
|
|||
|
||||
warningDialog.Dispose();
|
||||
}
|
||||
|
||||
private void PurgeShaderCache_Clicked(object sender, EventArgs args)
|
||||
{
|
||||
string[] tableEntry = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n");
|
||||
string titleId = tableEntry[1].ToLower();
|
||||
|
||||
DirectoryInfo shaderCacheDir = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, titleId, "cache", "shader"));
|
||||
|
||||
MessageDialog warningDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null)
|
||||
{
|
||||
Title = "Ryujinx - Warning",
|
||||
Text = $"You are about to delete the shader cache for '{tableEntry[0]}'. Are you sure you want to proceed?",
|
||||
WindowPosition = WindowPosition.Center
|
||||
};
|
||||
|
||||
List<DirectoryInfo> cacheDirectory = new List<DirectoryInfo>();
|
||||
|
||||
if (shaderCacheDir.Exists) { cacheDirectory.AddRange(shaderCacheDir.EnumerateDirectories("*")); }
|
||||
|
||||
if (cacheDirectory.Count > 0 && warningDialog.Run() == (int)ResponseType.Yes)
|
||||
{
|
||||
foreach (DirectoryInfo directory in cacheDirectory)
|
||||
{
|
||||
try
|
||||
{
|
||||
directory.Delete(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Error purging shader cache {directory.Name}: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
warningDialog.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace Ryujinx.Ui
|
|||
public static GlRenderer GlWidget => _glWidget;
|
||||
|
||||
private static AutoResetEvent _deviceExitStatus = new AutoResetEvent(false);
|
||||
private static AutoResetEvent _widgetInitEvent = new AutoResetEvent(false);
|
||||
|
||||
private static ListStore _tableStore;
|
||||
|
||||
|
@ -433,6 +434,30 @@ namespace Ryujinx.Ui
|
|||
}
|
||||
}
|
||||
|
||||
_widgetInitEvent.Reset();
|
||||
|
||||
#if MACOS_BUILD
|
||||
CreateGameWindow(device);
|
||||
#else
|
||||
Thread windowThread = new Thread(() =>
|
||||
{
|
||||
CreateGameWindow(device);
|
||||
})
|
||||
{
|
||||
Name = "GUI.WindowThread"
|
||||
};
|
||||
|
||||
windowThread.Start();
|
||||
#endif
|
||||
|
||||
_widgetInitEvent.WaitOne();
|
||||
|
||||
// Make sure the widget get initialized by forcing an update of GTK
|
||||
while (Application.EventsPending())
|
||||
{
|
||||
Application.RunIteration();
|
||||
}
|
||||
|
||||
Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}");
|
||||
|
||||
if (Directory.Exists(path))
|
||||
|
@ -493,25 +518,24 @@ namespace Ryujinx.Ui
|
|||
return;
|
||||
}
|
||||
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(device.Application.TitleName) ? string.Empty
|
||||
: $" - {device.Application.TitleName}";
|
||||
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(device.Application.DisplayVersion) ? string.Empty
|
||||
: $" v{device.Application.DisplayVersion}";
|
||||
|
||||
string titleIdSection = string.IsNullOrWhiteSpace(device.Application.TitleIdText) ? string.Empty
|
||||
: $" ({device.Application.TitleIdText.ToUpper()})";
|
||||
|
||||
string titleArchSection = device.Application.TitleIs64Bit ? " (64-bit)" : " (32-bit)";
|
||||
|
||||
Title = $"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
|
||||
|
||||
_emulationContext = device;
|
||||
_gamePath = path;
|
||||
|
||||
_deviceExitStatus.Reset();
|
||||
|
||||
#if MACOS_BUILD
|
||||
CreateGameWindow(device);
|
||||
#else
|
||||
Thread windowThread = new Thread(() =>
|
||||
{
|
||||
CreateGameWindow(device);
|
||||
})
|
||||
{
|
||||
Name = "GUI.WindowThread"
|
||||
};
|
||||
|
||||
windowThread.Start();
|
||||
#endif
|
||||
|
||||
_gameLoaded = true;
|
||||
_stopEmulation.Sensitive = true;
|
||||
|
||||
|
@ -534,7 +558,7 @@ namespace Ryujinx.Ui
|
|||
_windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1);
|
||||
}
|
||||
|
||||
_glWidget = new GlRenderer(_emulationContext, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
|
||||
_glWidget = new GlRenderer(device, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
|
||||
|
||||
Application.Invoke(delegate
|
||||
{
|
||||
|
@ -551,6 +575,8 @@ namespace Ryujinx.Ui
|
|||
}
|
||||
});
|
||||
|
||||
_widgetInitEvent.Set();
|
||||
|
||||
_glWidget.WaitEvent.WaitOne();
|
||||
|
||||
_glWidget.Start();
|
||||
|
@ -658,6 +684,7 @@ namespace Ryujinx.Ui
|
|||
Graphics.Gpu.GraphicsConfig.ResScale = (resScale == -1) ? resScaleCustom : resScale;
|
||||
Graphics.Gpu.GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy;
|
||||
Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
|
||||
Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
|
||||
}
|
||||
|
||||
public static void SaveConfig()
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace Ryujinx.Ui
|
|||
[GUI] CheckButton _discordToggle;
|
||||
[GUI] CheckButton _checkUpdatesToggle;
|
||||
[GUI] CheckButton _vSyncToggle;
|
||||
[GUI] CheckButton _shaderCacheToggle;
|
||||
[GUI] CheckButton _multiSchedToggle;
|
||||
[GUI] CheckButton _ptcToggle;
|
||||
[GUI] CheckButton _fsicToggle;
|
||||
|
@ -182,6 +183,11 @@ namespace Ryujinx.Ui
|
|||
_vSyncToggle.Click();
|
||||
}
|
||||
|
||||
if (ConfigurationState.Instance.Graphics.EnableShaderCache)
|
||||
{
|
||||
_shaderCacheToggle.Click();
|
||||
}
|
||||
|
||||
if (ConfigurationState.Instance.System.EnableMulticoreScheduling)
|
||||
{
|
||||
_multiSchedToggle.Click();
|
||||
|
@ -528,6 +534,7 @@ namespace Ryujinx.Ui
|
|||
ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
|
||||
ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active;
|
||||
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
|
||||
ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active;
|
||||
ConfigurationState.Instance.System.EnableMulticoreScheduling.Value = _multiSchedToggle.Active;
|
||||
ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
|
||||
ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active;
|
||||
|
|
|
@ -1701,6 +1701,24 @@
|
|||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="_shaderCacheToggle">
|
||||
<property name="label" translatable="yes">Enable Shader Cache</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Enables or disables Shader Cache</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
|
@ -1762,7 +1780,7 @@
|
|||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">0</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -1817,7 +1835,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue