Compare commits

...

8 Commits

Author SHA1 Message Date
Otozinclus
d10a478cce Shader translation delay hack (#469)
A workaround to avoid a freeze when translating shaders with the Metal
backend, that would happen after changing version or going from Vulkan
to Metal. 

Adds a delay in milliseconds, configurable in the UI behind the Dirty Hacks mechanism.

---------

Co-authored-by: Evan Husted <greem@greemdev.net>
2024-12-30 01:12:51 -06:00
Evan Husted
ec1020b165 UI: Dirty hacks clarification [ci skip] 2024-12-30 01:10:40 -06:00
Evan Husted
4082ebad1a Fix PR builds 2024-12-30 00:35:43 -06:00
Evan Husted
da8ea06074 misc: Small cleanups 2024-12-30 00:14:55 -06:00
Evan Husted
7f9dccb293 misc: chore: Cleanup DummyHardwareDeviceDriver.cs 2024-12-30 00:09:31 -06:00
Evan Husted
8e4a77aba0 UI: Text in the shader translation slider tooltip 2024-12-30 00:09:19 -06:00
Evan Husted
8fd8a776c9 misc: prevent crashes 2024-12-29 23:39:40 -06:00
Evan Husted
eec92c242c misc: Remove shader translation delay dirty hack from UI
it doesn't do anything
2024-12-29 22:55:33 -06:00
8 changed files with 45 additions and 25 deletions

View File

@@ -13,7 +13,7 @@ mkdir -p AppDir/usr/bin
cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop
cp distribution/linux/appimage/AppRun AppDir/AppRun cp distribution/linux/appimage/AppRun AppDir/AppRun
cp src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png AppDir/Ryujinx.svg cp distribution/misc/Logo.svg AppDir/Ryujinx.svg
cp -r "$BUILDDIR"/* AppDir/usr/bin/ cp -r "$BUILDDIR"/* AppDir/usr/bin/

View File

@@ -9,20 +9,12 @@ namespace Ryujinx.Audio.Backends.Dummy
{ {
public class DummyHardwareDeviceDriver : IHardwareDeviceDriver public class DummyHardwareDeviceDriver : IHardwareDeviceDriver
{ {
private readonly ManualResetEvent _updateRequiredEvent; private readonly ManualResetEvent _updateRequiredEvent = new(false);
private readonly ManualResetEvent _pauseEvent; private readonly ManualResetEvent _pauseEvent = new(true);
public static bool IsSupported => true; public static bool IsSupported => true;
public float Volume { get; set; } public float Volume { get; set; } = 1f;
public DummyHardwareDeviceDriver()
{
_updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true);
Volume = 1f;
}
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount) public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
{ {
@@ -60,7 +52,7 @@ namespace Ryujinx.Audio.Backends.Dummy
Dispose(true); Dispose(true);
} }
protected virtual void Dispose(bool disposing) private void Dispose(bool disposing)
{ {
if (disposing) if (disposing)
{ {

View File

@@ -13,13 +13,13 @@ namespace Ryujinx.Common.Configuration
public record EnabledDirtyHack(DirtyHacks Hack, int Value) public record EnabledDirtyHack(DirtyHacks Hack, int Value)
{ {
private static readonly byte[] _packedFormat = [8, 32]; public static readonly byte[] PackedFormat = [8, 32];
public ulong Pack() => BitTricks.PackBitFields([(uint)Hack, (uint)Value], _packedFormat); public ulong Pack() => BitTricks.PackBitFields([(uint)Hack, (uint)Value], PackedFormat);
public static EnabledDirtyHack FromPacked(ulong packedHack) public static EnabledDirtyHack Unpack(ulong packedHack)
{ {
var unpackedFields = BitTricks.UnpackBitFields(packedHack, _packedFormat); var unpackedFields = BitTricks.UnpackBitFields(packedHack, PackedFormat);
if (unpackedFields is not [var hack, var value]) if (unpackedFields is not [var hack, var value])
throw new ArgumentException(nameof(packedHack)); throw new ArgumentException(nameof(packedHack));
@@ -39,12 +39,21 @@ namespace Ryujinx.Common.Configuration
public DirtyHackCollection(ulong[] packedHacks) public DirtyHackCollection(ulong[] packedHacks)
{ {
foreach ((DirtyHacks dirtyHacks, int value) in packedHacks.Select(EnabledDirtyHack.FromPacked)) foreach ((DirtyHacks dirtyHacks, int value) in packedHacks.Select(EnabledDirtyHack.Unpack))
{ {
Add(dirtyHacks, value); Add(dirtyHacks, value);
} }
} }
public ulong[] PackEntries() =>
this
.Select(it =>
BitTricks.PackBitFields([(uint)it.Key, (uint)it.Value], EnabledDirtyHack.PackedFormat))
.ToArray();
public static implicit operator DirtyHackCollection(EnabledDirtyHack[] hacks) => new(hacks);
public static implicit operator DirtyHackCollection(ulong[] packedHacks) => new(packedHacks);
public new int this[DirtyHacks hack] => TryGetValue(hack, out var value) ? value : -1; public new int this[DirtyHacks hack] => TryGetValue(hack, out var value) ? value : -1;
public bool IsEnabled(DirtyHacks hack) => ContainsKey(hack); public bool IsEnabled(DirtyHacks hack) => ContainsKey(hack);

View File

@@ -1,3 +1,4 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
@@ -366,6 +367,9 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
{ {
try try
{ {
if (_context.DirtyHacks.IsEnabled(DirtyHacks.ShaderCompilationThreadSleep))
Thread.Sleep(_context.DirtyHacks[DirtyHacks.ShaderCompilationThreadSleep]);
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute); AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken); _asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
} }

View File

@@ -301,6 +301,8 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public string ShaderTranslationDelayTooltipText => $"Current value: {ShaderTranslationDelay}";
public int ShaderTranslationDelay public int ShaderTranslationDelay
{ {
get => _shaderTranslationSleepDelay; get => _shaderTranslationSleepDelay;
@@ -308,7 +310,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
_shaderTranslationSleepDelay = value; _shaderTranslationSleepDelay = value;
OnPropertyChanged(); OnPropertiesChanged(nameof(ShaderTranslationDelay), nameof(ShaderTranslationDelayTooltipText));
} }
} }

View File

@@ -29,7 +29,7 @@
<TextBlock <TextBlock
Foreground="{DynamicResource SecondaryTextColor}" Foreground="{DynamicResource SecondaryTextColor}"
TextDecorations="Underline" TextDecorations="Underline"
Text="Game-specific hacks &amp; tricks to alleviate performance issues or crashing. May cause issues." /> Text="Game-specific hacks &amp; tricks to alleviate performance issues or crashing. Will cause issues." />
<StackPanel <StackPanel
Margin="0,10,0,0" Margin="0,10,0,0"
Orientation="Horizontal" Orientation="Horizontal"
@@ -56,7 +56,7 @@
</StackPanel> </StackPanel>
<Slider HorizontalAlignment="Center" <Slider HorizontalAlignment="Center"
Value="{Binding ShaderTranslationDelay}" Value="{Binding ShaderTranslationDelay}"
ToolTip.Tip="{Binding ShaderTranslationDelay}" ToolTip.Tip="{Binding ShaderTranslationDelayTooltipText}"
Width="175" Width="175"
Margin="0,-3,0,0" Margin="0,-3,0,0"
Height="32" Height="32"

View File

@@ -752,11 +752,12 @@ namespace Ryujinx.Ava.Utilities.Configuration
Hacks.ShowDirtyHacks.Value = configurationFileFormat.ShowDirtyHacks; Hacks.ShowDirtyHacks.Value = configurationFileFormat.ShowDirtyHacks;
{ {
EnabledDirtyHack[] hacks = configurationFileFormat.DirtyHacks.Select(EnabledDirtyHack.FromPacked).ToArray(); EnabledDirtyHack[] hacks = (configurationFileFormat.DirtyHacks ?? []).Select(EnabledDirtyHack.Unpack).ToArray();
Hacks.Xc2MenuSoftlockFix.Value = hacks.Any(it => it.Hack == DirtyHacks.Xc2MenuSoftlockFix); Hacks.Xc2MenuSoftlockFix.Value = hacks.Any(it => it.Hack == DirtyHacks.Xc2MenuSoftlockFix);
var shaderCompilationThreadSleep = hacks.FirstOrDefault(it => it.Hack == DirtyHacks.ShaderCompilationThreadSleep); var shaderCompilationThreadSleep = hacks.FirstOrDefault(it =>
it.Hack == DirtyHacks.ShaderCompilationThreadSleep);
Hacks.EnableShaderCompilationThreadSleep.Value = shaderCompilationThreadSleep != null; Hacks.EnableShaderCompilationThreadSleep.Value = shaderCompilationThreadSleep != null;
Hacks.ShaderCompilationThreadSleepDelay.Value = shaderCompilationThreadSleep?.Value ?? 0; Hacks.ShaderCompilationThreadSleepDelay.Value = shaderCompilationThreadSleep?.Value ?? 0;
} }

View File

@@ -10,6 +10,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE; using Ryujinx.HLE;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using RyuLogger = Ryujinx.Common.Logging.Logger;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.Ava.Utilities.Configuration
{ {
@@ -644,8 +645,19 @@ namespace Ryujinx.Ava.Utilities.Configuration
private void HackChanged(object sender, ReactiveEventArgs<bool> rxe) private void HackChanged(object sender, ReactiveEventArgs<bool> rxe)
{ {
Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"EnabledDirtyHacks set to: [{EnabledHacks.Select(x => x.Hack).JoinToString(", ")}]", "LogValueChange"); var newHacks = EnabledHacks.Select(x => x.Hack)
.JoinToString(", ");
if (newHacks != _lastHackCollection)
{
RyuLogger.Info?.Print(LogClass.Configuration,
$"EnabledDirtyHacks set to: [{_lastHackCollection}]", "LogValueChange");
_lastHackCollection = newHacks;
} }
}
private static string _lastHackCollection;
public EnabledDirtyHack[] EnabledHacks public EnabledDirtyHack[] EnabledHacks
{ {