Merge branch 'applehv/force-ordered-atomics' into 'master'
Cpu: add option to force all exclusive memory accesses to be ordered on AppleHv. See merge request [ryubing/ryujinx!198](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/198)merge-requests/198/merge
commit
cd642746b6
|
|
@ -267,6 +267,31 @@
|
||||||
"zh_TW": "使用 Hypervisor"
|
"zh_TW": "使用 Hypervisor"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "SettingsTabSystemHvForceOrderedAtomics",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Force Ordered Atomics on Hypervisor",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "MenuBarFile",
|
"ID": "MenuBarFile",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|
@ -16518,6 +16543,31 @@
|
||||||
"zh_TW": "使用 Hypervisor 取代 JIT。使用時可大幅提高效能,但在目前狀態下可能不穩定。"
|
"zh_TW": "使用 Hypervisor 取代 JIT。使用時可大幅提高效能,但在目前狀態下可能不穩定。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "HvForceOrderedAtomicsTooltip",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Force all exclusive memory accesses to be ordered on Hypervisor.\n\nSome games like The Legend of Zelda: Breath of the Wild and Splatoon 2 require this setting to be ON when using Hypervisor to prevent softlocks and crashes.\n\nLeave OFF if unsure.",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "DRamTooltip",
|
"ID": "DRamTooltip",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Intrinsics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Cpu.AppleHv
|
||||||
|
{
|
||||||
|
static class HvCodePatcher
|
||||||
|
{
|
||||||
|
private const uint XMask = 0x3f808000u;
|
||||||
|
private const uint XValue = 0x8000000u;
|
||||||
|
|
||||||
|
private const uint ZrIndex = 31u;
|
||||||
|
|
||||||
|
public static void RewriteUnorderedExclusiveInstructions(Span<byte> code)
|
||||||
|
{
|
||||||
|
Span<uint> codeUint = MemoryMarshal.Cast<byte, uint>(code);
|
||||||
|
Span<Vector128<uint>> codeVector = MemoryMarshal.Cast<byte, Vector128<uint>>(code);
|
||||||
|
|
||||||
|
Vector128<uint> mask = Vector128.Create(XMask);
|
||||||
|
Vector128<uint> value = Vector128.Create(XValue);
|
||||||
|
|
||||||
|
for (int index = 0; index < codeVector.Length; index++)
|
||||||
|
{
|
||||||
|
Vector128<uint> v = codeVector[index];
|
||||||
|
|
||||||
|
if (Vector128.EqualsAny(Vector128.BitwiseAnd(v, mask), value))
|
||||||
|
{
|
||||||
|
int baseIndex = index * 4;
|
||||||
|
|
||||||
|
for (int instIndex = baseIndex; instIndex < baseIndex + 4; instIndex++)
|
||||||
|
{
|
||||||
|
ref uint inst = ref codeUint[instIndex];
|
||||||
|
|
||||||
|
if ((inst & XMask) != XValue)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPair = (inst & (1u << 21)) != 0;
|
||||||
|
bool isLoad = (inst & (1u << 22)) != 0;
|
||||||
|
|
||||||
|
uint rt2 = (inst >> 10) & 0x1fu;
|
||||||
|
uint rs = (inst >> 16) & 0x1fu;
|
||||||
|
|
||||||
|
if (isLoad && rs != ZrIndex)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPair && rt2 != ZrIndex)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the ordered flag.
|
||||||
|
inst |= 1u << 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,8 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
private readonly MemoryBlock _backingMemory;
|
private readonly MemoryBlock _backingMemory;
|
||||||
private readonly PageTable<ulong> _pageTable;
|
private readonly PageTable<ulong> _pageTable;
|
||||||
|
|
||||||
|
private readonly bool _forceOrderedAtomics;
|
||||||
|
|
||||||
private readonly ManagedPageFlags _pages;
|
private readonly ManagedPageFlags _pages;
|
||||||
|
|
||||||
public bool UsesPrivateAllocations => false;
|
public bool UsesPrivateAllocations => false;
|
||||||
|
|
@ -46,11 +48,13 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="backingMemory">Physical backing memory where virtual memory will be mapped to</param>
|
/// <param name="backingMemory">Physical backing memory where virtual memory will be mapped to</param>
|
||||||
/// <param name="addressSpaceSize">Size of the address space</param>
|
/// <param name="addressSpaceSize">Size of the address space</param>
|
||||||
|
/// <param name="forceOrderedAtomics">Force all exclusive memory accesses to be ordered</param>
|
||||||
/// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param>
|
/// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param>
|
||||||
public HvMemoryManager(MemoryBlock backingMemory, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler = null)
|
public HvMemoryManager(MemoryBlock backingMemory, ulong addressSpaceSize, bool forceOrderedAtomics, InvalidAccessHandler invalidAccessHandler = null)
|
||||||
{
|
{
|
||||||
_backingMemory = backingMemory;
|
_backingMemory = backingMemory;
|
||||||
_pageTable = new PageTable<ulong>();
|
_pageTable = new PageTable<ulong>();
|
||||||
|
_forceOrderedAtomics = forceOrderedAtomics;
|
||||||
_invalidAccessHandler = invalidAccessHandler;
|
_invalidAccessHandler = invalidAccessHandler;
|
||||||
AddressSpaceSize = addressSpaceSize;
|
AddressSpaceSize = addressSpaceSize;
|
||||||
|
|
||||||
|
|
@ -317,6 +321,18 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
|
|
||||||
public void Reprotect(ulong va, ulong size, MemoryPermission protection)
|
public void Reprotect(ulong va, ulong size, MemoryPermission protection)
|
||||||
{
|
{
|
||||||
|
if (_forceOrderedAtomics && protection.HasFlag(MemoryPermission.Execute))
|
||||||
|
{
|
||||||
|
// Some applications use unordered exclusive memory access instructions
|
||||||
|
// where it is not valid to do so, leading to memory re-ordering that
|
||||||
|
// makes the code behave incorrectly on some CPUs.
|
||||||
|
// To work around this, we force all such accesses to be ordered.
|
||||||
|
|
||||||
|
using WritableRegion writableRegion = GetWritableRegion(va, (int)size);
|
||||||
|
|
||||||
|
HvCodePatcher.RewriteUnorderedExclusiveInstructions(writableRegion.Memory.Span);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
if (OperatingSystem.IsMacOS() && isArm64Host && for64Bit && context.Device.Configuration.UseHypervisor)
|
if (OperatingSystem.IsMacOS() && isArm64Host && for64Bit && context.Device.Configuration.UseHypervisor)
|
||||||
{
|
{
|
||||||
HvEngine cpuEngine = new(_tickSource);
|
HvEngine cpuEngine = new(_tickSource);
|
||||||
HvMemoryManager memoryManager = new(context.Memory, addressSpaceSize, invalidAccessHandler);
|
HvMemoryManager memoryManager = new(context.Memory, addressSpaceSize, context.Device.Configuration.HvForceOrderedAtomics, invalidAccessHandler);
|
||||||
processContext = new ArmProcessContext<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
processContext = new ArmProcessContext<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,11 @@ namespace Ryujinx.HLE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal readonly bool UseHypervisor;
|
internal readonly bool UseHypervisor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Force all exclusive memory accesses to be ordered on Hypervisor.
|
||||||
|
/// </summary>
|
||||||
|
internal readonly bool HvForceOrderedAtomics;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiplayer LAN Interface ID (device GUID)
|
/// Multiplayer LAN Interface ID (device GUID)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -232,6 +237,7 @@ namespace Ryujinx.HLE
|
||||||
AspectRatio aspectRatio,
|
AspectRatio aspectRatio,
|
||||||
float audioVolume,
|
float audioVolume,
|
||||||
bool useHypervisor,
|
bool useHypervisor,
|
||||||
|
bool hvForceOrderedAtomics,
|
||||||
string multiplayerLanInterfaceId,
|
string multiplayerLanInterfaceId,
|
||||||
MultiplayerMode multiplayerMode,
|
MultiplayerMode multiplayerMode,
|
||||||
bool multiplayerDisableP2p,
|
bool multiplayerDisableP2p,
|
||||||
|
|
@ -261,6 +267,7 @@ namespace Ryujinx.HLE
|
||||||
AspectRatio = aspectRatio;
|
AspectRatio = aspectRatio;
|
||||||
AudioVolume = audioVolume;
|
AudioVolume = audioVolume;
|
||||||
UseHypervisor = useHypervisor;
|
UseHypervisor = useHypervisor;
|
||||||
|
HvForceOrderedAtomics = hvForceOrderedAtomics;
|
||||||
MultiplayerLanInterfaceId = multiplayerLanInterfaceId;
|
MultiplayerLanInterfaceId = multiplayerLanInterfaceId;
|
||||||
MultiplayerMode = multiplayerMode;
|
MultiplayerMode = multiplayerMode;
|
||||||
MultiplayerDisableP2p = multiplayerDisableP2p;
|
MultiplayerDisableP2p = multiplayerDisableP2p;
|
||||||
|
|
|
||||||
|
|
@ -333,6 +333,7 @@ namespace Ryujinx.Headless
|
||||||
options.AspectRatio,
|
options.AspectRatio,
|
||||||
options.AudioVolume,
|
options.AudioVolume,
|
||||||
options.UseHypervisor ?? true,
|
options.UseHypervisor ?? true,
|
||||||
|
options.HvForceOrderedAtomics,
|
||||||
options.MultiplayerLanInterfaceId,
|
options.MultiplayerLanInterfaceId,
|
||||||
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
||||||
false,
|
false,
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,9 @@ namespace Ryujinx.Headless
|
||||||
if (NeedsOverride(nameof(UseHypervisor)) && OperatingSystem.IsMacOS())
|
if (NeedsOverride(nameof(UseHypervisor)) && OperatingSystem.IsMacOS())
|
||||||
UseHypervisor = configurationState.System.UseHypervisor;
|
UseHypervisor = configurationState.System.UseHypervisor;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(HvForceOrderedAtomics)) && OperatingSystem.IsMacOS())
|
||||||
|
HvForceOrderedAtomics = configurationState.System.HvForceOrderedAtomics;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(MultiplayerLanInterfaceId)))
|
if (NeedsOverride(nameof(MultiplayerLanInterfaceId)))
|
||||||
MultiplayerLanInterfaceId = configurationState.Multiplayer.LanInterfaceId;
|
MultiplayerLanInterfaceId = configurationState.Multiplayer.LanInterfaceId;
|
||||||
|
|
||||||
|
|
@ -339,6 +342,9 @@ namespace Ryujinx.Headless
|
||||||
[Option("use-hypervisor", Required = false, Default = true, HelpText = "Uses Hypervisor over JIT if available.")]
|
[Option("use-hypervisor", Required = false, Default = true, HelpText = "Uses Hypervisor over JIT if available.")]
|
||||||
public bool? UseHypervisor { get; set; }
|
public bool? UseHypervisor { get; set; }
|
||||||
|
|
||||||
|
[Option("hv-force-ordered-atomics", Required = false, Default = false, HelpText = "Forces all exclusive memory accesses to be ordered on Hypervisor.")]
|
||||||
|
public bool HvForceOrderedAtomics { get; set; }
|
||||||
|
|
||||||
[Option("lan-interface-id", Required = false, Default = "0", HelpText = "GUID for the network interface used by LAN.")]
|
[Option("lan-interface-id", Required = false, Default = "0", HelpText = "GUID for the network interface used by LAN.")]
|
||||||
public string MultiplayerLanInterfaceId { get; set; }
|
public string MultiplayerLanInterfaceId { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of the file format
|
/// The current version of the file format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CurrentVersion = 70;
|
public const int CurrentVersion = 71;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the configuration file format
|
/// Version of the configuration file format
|
||||||
|
|
@ -464,6 +464,11 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseHypervisor { get; set; }
|
public bool UseHypervisor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Force all exclusive memory accesses to be ordered on Hypervisor.
|
||||||
|
/// </summary>
|
||||||
|
public bool HvForceOrderedAtomics { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables or disables the GDB stub
|
/// Enables or disables the GDB stub
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
System.IgnoreControllerApplet.Value = cff.IgnoreApplet;
|
System.IgnoreControllerApplet.Value = cff.IgnoreApplet;
|
||||||
System.SkipUserProfilesManager.Value = cff.SkipUserProfiles;
|
System.SkipUserProfilesManager.Value = cff.SkipUserProfiles;
|
||||||
System.UseHypervisor.Value = cff.UseHypervisor;
|
System.UseHypervisor.Value = cff.UseHypervisor;
|
||||||
|
System.HvForceOrderedAtomics.Value = cff.HvForceOrderedAtomics;
|
||||||
|
|
||||||
UI.GuiColumns.FavColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FavColumn : UI.GuiColumns.FavColumn.Value;
|
UI.GuiColumns.FavColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FavColumn : UI.GuiColumns.FavColumn.Value;
|
||||||
UI.GuiColumns.IconColumn.Value = shouldLoadFromFile ? cff.GuiColumns.IconColumn : UI.GuiColumns.IconColumn.Value;
|
UI.GuiColumns.IconColumn.Value = shouldLoadFromFile ? cff.GuiColumns.IconColumn : UI.GuiColumns.IconColumn.Value;
|
||||||
|
|
@ -484,7 +485,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
(69, static cff => cff.SkipUserProfiles = false)
|
(69, static cff => cff.SkipUserProfiles = false),
|
||||||
|
(70, static cff => cff.HvForceOrderedAtomics = false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -412,6 +412,11 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> UseHypervisor { get; private set; }
|
public ReactiveObject<bool> UseHypervisor { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Force all exclusive memory accesses to be ordered on Hypervisor.
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> HvForceOrderedAtomics { get; private set; }
|
||||||
|
|
||||||
public SystemSection()
|
public SystemSection()
|
||||||
{
|
{
|
||||||
Language = new ReactiveObject<Language>();
|
Language = new ReactiveObject<Language>();
|
||||||
|
|
@ -465,6 +470,8 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
AudioVolume.LogChangesToValue(nameof(AudioVolume));
|
AudioVolume.LogChangesToValue(nameof(AudioVolume));
|
||||||
UseHypervisor = new ReactiveObject<bool>();
|
UseHypervisor = new ReactiveObject<bool>();
|
||||||
UseHypervisor.LogChangesToValue(nameof(UseHypervisor));
|
UseHypervisor.LogChangesToValue(nameof(UseHypervisor));
|
||||||
|
HvForceOrderedAtomics = new ReactiveObject<bool>();
|
||||||
|
HvForceOrderedAtomics.LogChangesToValue(nameof(HvForceOrderedAtomics));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -936,6 +943,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
Graphics.AspectRatio,
|
Graphics.AspectRatio,
|
||||||
System.AudioVolume,
|
System.AudioVolume,
|
||||||
System.UseHypervisor,
|
System.UseHypervisor,
|
||||||
|
System.HvForceOrderedAtomics,
|
||||||
Multiplayer.LanInterfaceId,
|
Multiplayer.LanInterfaceId,
|
||||||
Multiplayer.Mode,
|
Multiplayer.Mode,
|
||||||
Multiplayer.DisableP2p,
|
Multiplayer.DisableP2p,
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
IgnoreApplet = System.IgnoreControllerApplet,
|
IgnoreApplet = System.IgnoreControllerApplet,
|
||||||
SkipUserProfiles = System.SkipUserProfilesManager,
|
SkipUserProfiles = System.SkipUserProfilesManager,
|
||||||
UseHypervisor = System.UseHypervisor,
|
UseHypervisor = System.UseHypervisor,
|
||||||
|
HvForceOrderedAtomics = System.HvForceOrderedAtomics,
|
||||||
GuiColumns = new GuiColumns
|
GuiColumns = new GuiColumns
|
||||||
{
|
{
|
||||||
FavColumn = UI.GuiColumns.FavColumn,
|
FavColumn = UI.GuiColumns.FavColumn,
|
||||||
|
|
@ -215,6 +216,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
||||||
System.IgnoreControllerApplet.Value = false;
|
System.IgnoreControllerApplet.Value = false;
|
||||||
System.SkipUserProfilesManager.Value = false;
|
System.SkipUserProfilesManager.Value = false;
|
||||||
System.UseHypervisor.Value = true;
|
System.UseHypervisor.Value = true;
|
||||||
|
System.HvForceOrderedAtomics.Value = false;
|
||||||
Multiplayer.LanInterfaceId.Value = "0";
|
Multiplayer.LanInterfaceId.Value = "0";
|
||||||
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
|
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
|
||||||
Multiplayer.DisableP2p.Value = false;
|
Multiplayer.DisableP2p.Value = false;
|
||||||
|
|
|
||||||
|
|
@ -276,6 +276,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
public bool IsVulkanSelected =>
|
public bool IsVulkanSelected =>
|
||||||
GraphicsBackendIndex == 1 || (GraphicsBackendIndex == 0 && !OperatingSystem.IsMacOS());
|
GraphicsBackendIndex == 1 || (GraphicsBackendIndex == 0 && !OperatingSystem.IsMacOS());
|
||||||
public bool UseHypervisor { get; set; }
|
public bool UseHypervisor { get; set; }
|
||||||
|
public bool HvForceOrderedAtomics { get; set; }
|
||||||
public bool DisableP2P { get; set; }
|
public bool DisableP2P { get; set; }
|
||||||
|
|
||||||
public bool ShowDirtyHacks => ConfigurationState.Instance.Hacks.ShowDirtyHacks;
|
public bool ShowDirtyHacks => ConfigurationState.Instance.Hacks.ShowDirtyHacks;
|
||||||
|
|
@ -673,6 +674,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
EnableLowPowerPptc = config.System.EnableLowPowerPtc;
|
EnableLowPowerPptc = config.System.EnableLowPowerPtc;
|
||||||
MemoryMode = (int)config.System.MemoryManagerMode.Value;
|
MemoryMode = (int)config.System.MemoryManagerMode.Value;
|
||||||
UseHypervisor = config.System.UseHypervisor;
|
UseHypervisor = config.System.UseHypervisor;
|
||||||
|
HvForceOrderedAtomics = config.System.HvForceOrderedAtomics;
|
||||||
TurboMultiplier = config.System.TickScalar;
|
TurboMultiplier = config.System.TickScalar;
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
|
|
@ -784,6 +786,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||||
config.System.EnableLowPowerPtc.Value = EnableLowPowerPptc;
|
config.System.EnableLowPowerPtc.Value = EnableLowPowerPptc;
|
||||||
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
|
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
|
||||||
config.System.UseHypervisor.Value = UseHypervisor;
|
config.System.UseHypervisor.Value = UseHypervisor;
|
||||||
|
config.System.HvForceOrderedAtomics.Value = HvForceOrderedAtomics;
|
||||||
config.System.TickScalar.Value = TurboMultiplier;
|
config.System.TickScalar.Value = TurboMultiplier;
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,12 @@
|
||||||
<TextBlock Text="{ext:Locale SettingsTabSystemUseHypervisor}"
|
<TextBlock Text="{ext:Locale SettingsTabSystemUseHypervisor}"
|
||||||
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" />
|
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
<CheckBox IsChecked="{Binding HvForceOrderedAtomics}"
|
||||||
|
IsVisible="{x:Static helper:RunningPlatform.IsArmMac}"
|
||||||
|
ToolTip.Tip="{ext:Locale HvForceOrderedAtomicsTooltip}">
|
||||||
|
<TextBlock Text="{ext:Locale SettingsTabSystemHvForceOrderedAtomics}"
|
||||||
|
ToolTip.Tip="{ext:Locale HvForceOrderedAtomicsTooltip}" />
|
||||||
|
</CheckBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<Separator Height="1" />
|
<Separator Height="1" />
|
||||||
<StackPanel
|
<StackPanel
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue