Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b994dafe7a | ||
|
54421760c3 | ||
|
88a0e720cb | ||
|
53cc9e0561 | ||
|
7defc59b9d |
@@ -58,7 +58,6 @@ namespace ARMeilleure.CodeGen.Linking
|
|||||||
/// <param name="a">First instance</param>
|
/// <param name="a">First instance</param>
|
||||||
/// <param name="b">Second instance</param>
|
/// <param name="b">Second instance</param>
|
||||||
/// <returns><see langword="true"/> if not equal; otherwise <see langword="false"/></returns>
|
/// <returns><see langword="true"/> if not equal; otherwise <see langword="false"/></returns>
|
||||||
/// <inheritdoc/>
|
|
||||||
public static bool operator !=(Symbol a, Symbol b)
|
public static bool operator !=(Symbol a, Symbol b)
|
||||||
{
|
{
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
|
@@ -206,7 +206,7 @@ namespace ARMeilleure.Common
|
|||||||
/// <typeparam name="T">Type of elements</typeparam>
|
/// <typeparam name="T">Type of elements</typeparam>
|
||||||
/// <param name="length">Number of elements</param>
|
/// <param name="length">Number of elements</param>
|
||||||
/// <param name="fill">Fill value</param>
|
/// <param name="fill">Fill value</param>
|
||||||
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword=""="false"/></param>
|
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
|
||||||
/// <returns>Allocated block</returns>
|
/// <returns>Allocated block</returns>
|
||||||
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
|
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
@@ -9,6 +9,9 @@ namespace ARMeilleure.Common
|
|||||||
class Counter<T> : IDisposable where T : unmanaged
|
class Counter<T> : IDisposable where T : unmanaged
|
||||||
{
|
{
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
/// <summary>
|
||||||
|
/// Index in the <see cref="EntryTable{T}"/>
|
||||||
|
/// </summary>
|
||||||
private readonly int _index;
|
private readonly int _index;
|
||||||
private readonly EntryTable<T> _countTable;
|
private readonly EntryTable<T> _countTable;
|
||||||
|
|
||||||
@@ -17,7 +20,6 @@ namespace ARMeilleure.Common
|
|||||||
/// <see cref="EntryTable{T}"/> instance and index.
|
/// <see cref="EntryTable{T}"/> instance and index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="countTable"><see cref="EntryTable{T}"/> instance</param>
|
/// <param name="countTable"><see cref="EntryTable{T}"/> instance</param>
|
||||||
/// <param name="index">Index in the <see cref="EntryTable{T}"/></param>
|
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="countTable"/> is <see langword="null"/></exception>
|
/// <exception cref="ArgumentNullException"><paramref name="countTable"/> is <see langword="null"/></exception>
|
||||||
/// <exception cref="ArgumentException"><typeparamref name="T"/> is unsupported</exception>
|
/// <exception cref="ArgumentException"><typeparamref name="T"/> is unsupported</exception>
|
||||||
public Counter(EntryTable<T> countTable)
|
public Counter(EntryTable<T> countTable)
|
||||||
@@ -68,7 +70,7 @@ namespace ARMeilleure.Common
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases all unmanaged and optionally managed resources used by the <see cref="Counter{T}"/> instance.
|
/// Releases all unmanaged and optionally managed resources used by the <see cref="Counter{T}"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
|
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resources</param>
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!_disposed)
|
if (!_disposed)
|
||||||
|
@@ -344,7 +344,7 @@ namespace ARMeilleure.Translation
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the value from the dictionary after searching for it with <paramref name="key">.
|
/// Removes the value from the dictionary after searching for it with <paramref name="key"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Key to search for</param>
|
/// <param name="key">Key to search for</param>
|
||||||
/// <returns>Number of deleted values</returns>
|
/// <returns>Number of deleted values</returns>
|
||||||
|
@@ -52,8 +52,8 @@
|
|||||||
"GameListContextMenuOpenModsDirectory": "Open Mods Directory",
|
"GameListContextMenuOpenModsDirectory": "Open Mods Directory",
|
||||||
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
|
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
|
||||||
"GameListContextMenuCacheManagement": "Cache Management",
|
"GameListContextMenuCacheManagement": "Cache Management",
|
||||||
"GameListContextMenuCacheManagementPurgePptc": "Purge PPTC Cache",
|
"GameListContextMenuCacheManagementPurgePptc": "Queue PPTC Rebuild",
|
||||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "Deletes Application's PPTC cache",
|
"GameListContextMenuCacheManagementPurgePptcToolTip": "Trigger PPTC to rebuild at boot time on the next game launch",
|
||||||
"GameListContextMenuCacheManagementPurgeShaderCache": "Purge Shader Cache",
|
"GameListContextMenuCacheManagementPurgeShaderCache": "Purge Shader Cache",
|
||||||
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Deletes Application's shader cache",
|
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Deletes Application's shader cache",
|
||||||
"GameListContextMenuCacheManagementOpenPptcDirectory": "Open PPTC Directory",
|
"GameListContextMenuCacheManagementOpenPptcDirectory": "Open PPTC Directory",
|
||||||
@@ -350,7 +350,7 @@
|
|||||||
"DialogProfileDeleteProfileTitle": "Deleting Profile",
|
"DialogProfileDeleteProfileTitle": "Deleting Profile",
|
||||||
"DialogProfileDeleteProfileMessage": "This action is irreversible, are you sure you want to continue?",
|
"DialogProfileDeleteProfileMessage": "This action is irreversible, are you sure you want to continue?",
|
||||||
"DialogWarning": "Warning",
|
"DialogWarning": "Warning",
|
||||||
"DialogPPTCDeletionMessage": "You are about to delete the PPTC cache for :\n\n{0}\n\nAre you sure you want to proceed?",
|
"DialogPPTCDeletionMessage": "You are about to queue a PPTC rebuild on the next boot of:\n\n{0}\n\nAre you sure you want to proceed?",
|
||||||
"DialogPPTCDeletionErrorMessage": "Error purging PPTC cache at {0}: {1}",
|
"DialogPPTCDeletionErrorMessage": "Error purging PPTC cache at {0}: {1}",
|
||||||
"DialogShaderDeletionMessage": "You are about to delete the Shader cache for :\n\n{0}\n\nAre you sure you want to proceed?",
|
"DialogShaderDeletionMessage": "You are about to delete the Shader cache for :\n\n{0}\n\nAre you sure you want to proceed?",
|
||||||
"DialogShaderDeletionErrorMessage": "Error purging Shader cache at {0}: {1}",
|
"DialogShaderDeletionErrorMessage": "Error purging Shader cache at {0}: {1}",
|
||||||
|
@@ -49,6 +49,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
|||||||
private float _previousVolumeLevel;
|
private float _previousVolumeLevel;
|
||||||
private float _volume;
|
private float _volume;
|
||||||
private bool _isVulkanAvailable = true;
|
private bool _isVulkanAvailable = true;
|
||||||
|
private bool _directoryChanged = false;
|
||||||
private List<string> _gpuIds = new List<string>();
|
private List<string> _gpuIds = new List<string>();
|
||||||
private KeyboardHotkeys _keyboardHotkeys;
|
private KeyboardHotkeys _keyboardHotkeys;
|
||||||
private int _graphicsBackendIndex;
|
private int _graphicsBackendIndex;
|
||||||
@@ -112,6 +113,17 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DirectoryChanged
|
||||||
|
{
|
||||||
|
get => _directoryChanged;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_directoryChanged = value;
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool EnableDiscordIntegration { get; set; }
|
public bool EnableDiscordIntegration { get; set; }
|
||||||
public bool CheckUpdatesOnStart { get; set; }
|
public bool CheckUpdatesOnStart { get; set; }
|
||||||
public bool ShowConfirmExit { get; set; }
|
public bool ShowConfirmExit { get; set; }
|
||||||
@@ -397,10 +409,14 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
|||||||
|
|
||||||
public async Task SaveSettings()
|
public async Task SaveSettings()
|
||||||
{
|
{
|
||||||
List<string> gameDirs = new List<string>(GameDirectories);
|
|
||||||
|
|
||||||
ConfigurationState config = ConfigurationState.Instance;
|
ConfigurationState config = ConfigurationState.Instance;
|
||||||
|
|
||||||
|
if (_directoryChanged)
|
||||||
|
{
|
||||||
|
List<string> gameDirs = new List<string>(GameDirectories);
|
||||||
|
config.Ui.GameDirs.Value = gameDirs;
|
||||||
|
}
|
||||||
|
|
||||||
if (_validTzRegions.Contains(TimeZone))
|
if (_validTzRegions.Contains(TimeZone))
|
||||||
{
|
{
|
||||||
config.System.TimeZone.Value = TimeZone;
|
config.System.TimeZone.Value = TimeZone;
|
||||||
@@ -465,7 +481,6 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
|||||||
|
|
||||||
config.System.SystemTimeOffset.Value = systemTimeOffset.Seconds;
|
config.System.SystemTimeOffset.Value = systemTimeOffset.Seconds;
|
||||||
config.Graphics.ShadersDumpPath.Value = ShaderDumpPath;
|
config.Graphics.ShadersDumpPath.Value = ShaderDumpPath;
|
||||||
config.Ui.GameDirs.Value = gameDirs;
|
|
||||||
config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
|
config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
|
||||||
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
|
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
|
||||||
|
|
||||||
|
@@ -162,6 +162,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
|||||||
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path))
|
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path))
|
||||||
{
|
{
|
||||||
ViewModel.GameDirectories.Add(path);
|
ViewModel.GameDirectories.Add(path);
|
||||||
|
ViewModel.DirectoryChanged = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -170,6 +171,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
|||||||
if (!string.IsNullOrWhiteSpace(path))
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
{
|
{
|
||||||
ViewModel.GameDirectories.Add(path);
|
ViewModel.GameDirectories.Add(path);
|
||||||
|
ViewModel.DirectoryChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,6 +183,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
|||||||
foreach (string path in selected)
|
foreach (string path in selected)
|
||||||
{
|
{
|
||||||
ViewModel.GameDirectories.Remove(path);
|
ViewModel.GameDirectories.Remove(path);
|
||||||
|
ViewModel.DirectoryChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,10 +235,12 @@ namespace Ryujinx.Ava.Ui.Windows
|
|||||||
|
|
||||||
ControllerSettings?.SaveCurrentProfile();
|
ControllerSettings?.SaveCurrentProfile();
|
||||||
|
|
||||||
if (Owner is MainWindow window)
|
if (Owner is MainWindow window && ViewModel.DirectoryChanged)
|
||||||
{
|
{
|
||||||
window.ViewModel.LoadApplications();
|
window.ViewModel.LoadApplications();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewModel.DirectoryChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClosed(EventArgs e)
|
protected override void OnClosed(EventArgs e)
|
||||||
|
@@ -1317,10 +1317,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
for (int location = 0; location < attributeTypes.Length; location++)
|
for (int location = 0; location < attributeTypes.Length; location++)
|
||||||
{
|
{
|
||||||
attributeTypes[location] = vertexAttribState[location].UnpackType() switch
|
VertexAttribType type = vertexAttribState[location].UnpackType();
|
||||||
|
|
||||||
|
attributeTypes[location] = type switch
|
||||||
{
|
{
|
||||||
3 => AttributeType.Sint,
|
VertexAttribType.Sint => AttributeType.Sint,
|
||||||
4 => AttributeType.Uint,
|
VertexAttribType.Uint => AttributeType.Uint,
|
||||||
_ => AttributeType.Float
|
_ => AttributeType.Float
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -267,6 +267,41 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
#pragma warning restore CS0649
|
#pragma warning restore CS0649
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vertex attribute vector and component size.
|
||||||
|
/// </summary>
|
||||||
|
enum VertexAttribSize
|
||||||
|
{
|
||||||
|
Size32x4 = 1,
|
||||||
|
Size32x3 = 2,
|
||||||
|
Size16x4 = 3,
|
||||||
|
Size32x2 = 4,
|
||||||
|
Size16x3 = 5,
|
||||||
|
Size8x4 = 0xa,
|
||||||
|
Size16x2 = 0xf,
|
||||||
|
Size32 = 0x12,
|
||||||
|
Size8x3 = 0x13,
|
||||||
|
Size8x2 = 0x18,
|
||||||
|
Size16 = 0x1b,
|
||||||
|
Size8 = 0x1d,
|
||||||
|
Rgb10A2 = 0x30,
|
||||||
|
Rg11B10 = 0x31
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vertex attribute component type.
|
||||||
|
/// </summary>
|
||||||
|
enum VertexAttribType
|
||||||
|
{
|
||||||
|
Snorm = 1,
|
||||||
|
Unorm = 2,
|
||||||
|
Sint = 3,
|
||||||
|
Uint = 4,
|
||||||
|
Uscaled = 5,
|
||||||
|
Sscaled = 6,
|
||||||
|
Float = 7
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Vertex buffer attribute state.
|
/// Vertex buffer attribute state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -312,13 +347,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
return Attribute & 0x3fe00000;
|
return Attribute & 0x3fe00000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks the Maxwell attribute size.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Attribute size</returns>
|
||||||
|
public VertexAttribSize UnpackSize()
|
||||||
|
{
|
||||||
|
return (VertexAttribSize)((Attribute >> 21) & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unpacks the Maxwell attribute component type.
|
/// Unpacks the Maxwell attribute component type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Attribute component type</returns>
|
/// <returns>Attribute component type</returns>
|
||||||
public uint UnpackType()
|
public VertexAttribType UnpackType()
|
||||||
{
|
{
|
||||||
return (Attribute >> 27) & 7;
|
return (VertexAttribType)((Attribute >> 27) & 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Host hardware capabilities.
|
/// Host hardware capabilities.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal Capabilities Capabilities { get; private set; }
|
internal Capabilities Capabilities;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event for signalling shader cache loading progress.
|
/// Event for signalling shader cache loading progress.
|
||||||
|
@@ -573,9 +573,9 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
RecompileGraphicsFromGuestCode(guestShaders, specState, programIndex);
|
RecompileGraphicsFromGuestCode(guestShaders, specState, programIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DiskCacheLoadException diskCacheLoadException)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Gpu, $"Error translating guest shader. {diskCacheLoadException.Message}");
|
Logger.Error?.Print(LogClass.Gpu, $"Error translating guest shader. {exception.Message}");
|
||||||
|
|
||||||
ErrorCount++;
|
ErrorCount++;
|
||||||
SignalCompiled();
|
SignalCompiled();
|
||||||
|
@@ -27,7 +27,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
_stageIndex = stageIndex;
|
_stageIndex = stageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public int QueryBindingConstantBuffer(int index)
|
public int QueryBindingConstantBuffer(int index)
|
||||||
{
|
{
|
||||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
||||||
@@ -41,7 +40,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public int QueryBindingStorageBuffer(int index)
|
public int QueryBindingStorageBuffer(int index)
|
||||||
{
|
{
|
||||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
||||||
@@ -54,7 +52,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public int QueryBindingTexture(int index, bool isBuffer)
|
public int QueryBindingTexture(int index, bool isBuffer)
|
||||||
{
|
{
|
||||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
||||||
@@ -72,7 +69,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public int QueryBindingImage(int index, bool isBuffer)
|
public int QueryBindingImage(int index, bool isBuffer)
|
||||||
{
|
{
|
||||||
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
if (_context.Capabilities.Api == TargetApi.Vulkan)
|
||||||
@@ -116,37 +112,26 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostHasFrontFacingBug() => _context.Capabilities.HasFrontFacingBug;
|
public bool QueryHostHasFrontFacingBug() => _context.Capabilities.HasFrontFacingBug;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostHasVectorIndexingBug() => _context.Capabilities.HasVectorIndexingBug;
|
public bool QueryHostHasVectorIndexingBug() => _context.Capabilities.HasVectorIndexingBug;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
|
public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostSupportsBgraFormat() => _context.Capabilities.SupportsBgraFormat;
|
public bool QueryHostSupportsBgraFormat() => _context.Capabilities.SupportsBgraFormat;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostSupportsFragmentShaderInterlock() => _context.Capabilities.SupportsFragmentShaderInterlock;
|
public bool QueryHostSupportsFragmentShaderInterlock() => _context.Capabilities.SupportsFragmentShaderInterlock;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
|
public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostSupportsGeometryShaderPassthrough() => _context.Capabilities.SupportsGeometryShaderPassthrough;
|
public bool QueryHostSupportsGeometryShaderPassthrough() => _context.Capabilities.SupportsGeometryShaderPassthrough;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostSupportsImageLoadFormatted() => _context.Capabilities.SupportsImageLoadFormatted;
|
public bool QueryHostSupportsImageLoadFormatted() => _context.Capabilities.SupportsImageLoadFormatted;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostSupportsNonConstantTextureOffset() => _context.Capabilities.SupportsNonConstantTextureOffset;
|
public bool QueryHostSupportsNonConstantTextureOffset() => _context.Capabilities.SupportsNonConstantTextureOffset;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot;
|
public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;
|
public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
|
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||||
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader
|
namespace Ryujinx.Graphics.Shader
|
||||||
{
|
{
|
||||||
public enum AttributeType : byte
|
public enum AttributeType : byte
|
||||||
{
|
{
|
||||||
|
// Generic types.
|
||||||
Float,
|
Float,
|
||||||
Sint,
|
Sint,
|
||||||
Uint
|
Uint
|
||||||
@@ -11,18 +14,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
|
|
||||||
static class AttributeTypeExtensions
|
static class AttributeTypeExtensions
|
||||||
{
|
{
|
||||||
public static string GetScalarType(this AttributeType type)
|
public static string ToVec4Type(this AttributeType type)
|
||||||
{
|
|
||||||
return type switch
|
|
||||||
{
|
|
||||||
AttributeType.Float => "float",
|
|
||||||
AttributeType.Sint => "int",
|
|
||||||
AttributeType.Uint => "uint",
|
|
||||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetVec4Type(this AttributeType type)
|
|
||||||
{
|
{
|
||||||
return type switch
|
return type switch
|
||||||
{
|
{
|
||||||
@@ -32,5 +24,27 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static VariableType ToVariableType(this AttributeType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
AttributeType.Float => VariableType.F32,
|
||||||
|
AttributeType.Sint => VariableType.S32,
|
||||||
|
AttributeType.Uint => VariableType.U32,
|
||||||
|
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AggregateType ToAggregateType(this AttributeType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
AttributeType.Float => AggregateType.FP32,
|
||||||
|
AttributeType.Sint => AggregateType.S32,
|
||||||
|
AttributeType.Uint => AggregateType.U32,
|
||||||
|
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -553,11 +553,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
if (context.Config.Stage == ShaderStage.Vertex)
|
if (context.Config.Stage == ShaderStage.Vertex)
|
||||||
{
|
{
|
||||||
type = context.Config.GpuAccessor.QueryAttributeType(attr).GetVec4Type();
|
type = context.Config.GpuAccessor.QueryAttributeType(attr).ToVec4Type();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type = AttributeType.Float.GetVec4Type();
|
type = AttributeType.Float.ToVec4Type();
|
||||||
}
|
}
|
||||||
|
|
||||||
context.AppendLine($"layout ({pass}location = {attr}) {iq}in {type} {name}{suffix};");
|
context.AppendLine($"layout ({pass}location = {attr}) {iq}in {type} {name}{suffix};");
|
||||||
|
@@ -454,12 +454,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
AttributeType type = context.Config.GpuAccessor.QueryAttributeType(location);
|
AttributeType type = context.Config.GpuAccessor.QueryAttributeType(location);
|
||||||
|
|
||||||
return type switch
|
return type.ToVariableType();
|
||||||
{
|
|
||||||
AttributeType.Sint => VariableType.S32,
|
|
||||||
AttributeType.Uint => VariableType.U32,
|
|
||||||
_ => VariableType.F32
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -93,12 +93,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
if (config.Stage == ShaderStage.Vertex && !isOutAttr)
|
if (config.Stage == ShaderStage.Vertex && !isOutAttr)
|
||||||
{
|
{
|
||||||
elemType = config.GpuAccessor.QueryAttributeType(location) switch
|
elemType = config.GpuAccessor.QueryAttributeType(location).ToAggregateType();
|
||||||
{
|
|
||||||
AttributeType.Sint => AggregateType.S32,
|
|
||||||
AttributeType.Uint => AggregateType.U32,
|
|
||||||
_ => AggregateType.FP32
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -8,7 +8,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
class FormatCapabilities
|
class FormatCapabilities
|
||||||
{
|
{
|
||||||
private readonly FormatFeatureFlags[] _table;
|
private readonly FormatFeatureFlags[] _bufferTable;
|
||||||
|
private readonly FormatFeatureFlags[] _optimalTable;
|
||||||
|
|
||||||
private readonly Vk _api;
|
private readonly Vk _api;
|
||||||
private readonly PhysicalDevice _physicalDevice;
|
private readonly PhysicalDevice _physicalDevice;
|
||||||
@@ -17,14 +18,18 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_api = api;
|
_api = api;
|
||||||
_physicalDevice = physicalDevice;
|
_physicalDevice = physicalDevice;
|
||||||
_table = new FormatFeatureFlags[Enum.GetNames(typeof(GAL.Format)).Length];
|
|
||||||
|
int totalFormats = Enum.GetNames(typeof(GAL.Format)).Length;
|
||||||
|
|
||||||
|
_bufferTable = new FormatFeatureFlags[totalFormats];
|
||||||
|
_optimalTable = new FormatFeatureFlags[totalFormats];
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool FormatsSupports(FormatFeatureFlags flags, params GAL.Format[] formats)
|
public bool BufferFormatsSupport(FormatFeatureFlags flags, params GAL.Format[] formats)
|
||||||
{
|
{
|
||||||
foreach (GAL.Format format in formats)
|
foreach (GAL.Format format in formats)
|
||||||
{
|
{
|
||||||
if (!FormatSupports(flags, format))
|
if (!BufferFormatSupports(flags, format))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -33,15 +38,42 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool FormatSupports(FormatFeatureFlags flags, GAL.Format format)
|
public bool OptimalFormatsSupport(FormatFeatureFlags flags, params GAL.Format[] formats)
|
||||||
{
|
{
|
||||||
var formatFeatureFlags = _table[(int)format];
|
foreach (GAL.Format format in formats)
|
||||||
|
{
|
||||||
|
if (!OptimalFormatSupports(flags, format))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool BufferFormatSupports(FormatFeatureFlags flags, GAL.Format format)
|
||||||
|
{
|
||||||
|
var formatFeatureFlags = _bufferTable[(int)format];
|
||||||
|
|
||||||
|
if (formatFeatureFlags == 0)
|
||||||
|
{
|
||||||
|
_api.GetPhysicalDeviceFormatProperties(_physicalDevice, FormatTable.GetFormat(format), out var fp);
|
||||||
|
formatFeatureFlags = fp.BufferFeatures;
|
||||||
|
_bufferTable[(int)format] = formatFeatureFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (formatFeatureFlags & flags) == flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OptimalFormatSupports(FormatFeatureFlags flags, GAL.Format format)
|
||||||
|
{
|
||||||
|
var formatFeatureFlags = _optimalTable[(int)format];
|
||||||
|
|
||||||
if (formatFeatureFlags == 0)
|
if (formatFeatureFlags == 0)
|
||||||
{
|
{
|
||||||
_api.GetPhysicalDeviceFormatProperties(_physicalDevice, FormatTable.GetFormat(format), out var fp);
|
_api.GetPhysicalDeviceFormatProperties(_physicalDevice, FormatTable.GetFormat(format), out var fp);
|
||||||
formatFeatureFlags = fp.OptimalTilingFeatures;
|
formatFeatureFlags = fp.OptimalTilingFeatures;
|
||||||
_table[(int)format] = formatFeatureFlags;
|
_optimalTable[(int)format] = formatFeatureFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (formatFeatureFlags & flags) == flags;
|
return (formatFeatureFlags & flags) == flags;
|
||||||
@@ -69,7 +101,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
requiredFeatures |= FormatFeatureFlags.FormatFeatureStorageImageBit;
|
requiredFeatures |= FormatFeatureFlags.FormatFeatureStorageImageBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FormatSupports(requiredFeatures, srcFormat) || (IsD24S8(srcFormat) && VulkanConfiguration.ForceD24S8Unsupported))
|
if (!OptimalFormatSupports(requiredFeatures, srcFormat) || (IsD24S8(srcFormat) && VulkanConfiguration.ForceD24S8Unsupported))
|
||||||
{
|
{
|
||||||
// The format is not supported. Can we convert it to a higher precision format?
|
// The format is not supported. Can we convert it to a higher precision format?
|
||||||
if (IsD24S8(srcFormat))
|
if (IsD24S8(srcFormat))
|
||||||
@@ -85,9 +117,44 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VkFormat ConvertToVertexVkFormat(GAL.Format srcFormat)
|
||||||
|
{
|
||||||
|
var format = FormatTable.GetFormat(srcFormat);
|
||||||
|
|
||||||
|
if (!BufferFormatSupports(FormatFeatureFlags.FormatFeatureVertexBufferBit, srcFormat) ||
|
||||||
|
(IsRGB16IntFloat(srcFormat) && VulkanConfiguration.ForceRGB16IntFloatUnsupported))
|
||||||
|
{
|
||||||
|
// The format is not supported. Can we convert it to an alternative format?
|
||||||
|
switch (srcFormat)
|
||||||
|
{
|
||||||
|
case GAL.Format.R16G16B16Float:
|
||||||
|
format = VkFormat.R16G16B16A16Sfloat;
|
||||||
|
break;
|
||||||
|
case GAL.Format.R16G16B16Sint:
|
||||||
|
format = VkFormat.R16G16B16A16Sint;
|
||||||
|
break;
|
||||||
|
case GAL.Format.R16G16B16Uint:
|
||||||
|
format = VkFormat.R16G16B16A16Uint;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Logger.Error?.Print(LogClass.Gpu, $"Format {srcFormat} is not supported by the host.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsD24S8(GAL.Format format)
|
public static bool IsD24S8(GAL.Format format)
|
||||||
{
|
{
|
||||||
return format == GAL.Format.D24UnormS8Uint || format == GAL.Format.S8UintD24Unorm;
|
return format == GAL.Format.D24UnormS8Uint || format == GAL.Format.S8UintD24Unorm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsRGB16IntFloat(GAL.Format format)
|
||||||
|
{
|
||||||
|
return format == GAL.Format.R16G16B16Float ||
|
||||||
|
format == GAL.Format.R16G16B16Sint ||
|
||||||
|
format == GAL.Format.R16G16B16Uint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -730,6 +730,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
|
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
|
||||||
{
|
{
|
||||||
|
var formatCapabilities = Gd.FormatCapabilities;
|
||||||
|
|
||||||
int count = Math.Min(Constants.MaxVertexAttributes, vertexAttribs.Length);
|
int count = Math.Min(Constants.MaxVertexAttributes, vertexAttribs.Length);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
@@ -740,7 +742,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_newState.Internal.VertexAttributeDescriptions[i] = new VertexInputAttributeDescription(
|
_newState.Internal.VertexAttributeDescriptions[i] = new VertexInputAttributeDescription(
|
||||||
(uint)i,
|
(uint)i,
|
||||||
(uint)bufferIndex,
|
(uint)bufferIndex,
|
||||||
FormatTable.GetFormat(attribute.Format),
|
formatCapabilities.ConvertToVertexVkFormat(attribute.Format),
|
||||||
(uint)attribute.Offset);
|
(uint)attribute.Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -211,7 +211,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
pipeline.Internal.VertexAttributeDescriptions[i] = new VertexInputAttributeDescription(
|
pipeline.Internal.VertexAttributeDescriptions[i] = new VertexInputAttributeDescription(
|
||||||
(uint)i,
|
(uint)i,
|
||||||
(uint)bufferIndex,
|
(uint)bufferIndex,
|
||||||
FormatTable.GetFormat(attribute.Format),
|
gd.FormatCapabilities.ConvertToVertexVkFormat(attribute.Format),
|
||||||
(uint)attribute.Offset);
|
(uint)attribute.Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -451,8 +451,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (_gd.FormatCapabilities.FormatSupports(FormatFeatureFlags.FormatFeatureBlitSrcBit, srcFormat) &&
|
else if (_gd.FormatCapabilities.OptimalFormatSupports(FormatFeatureFlags.FormatFeatureBlitSrcBit, srcFormat) &&
|
||||||
_gd.FormatCapabilities.FormatSupports(FormatFeatureFlags.FormatFeatureBlitDstBit, dstFormat))
|
_gd.FormatCapabilities.OptimalFormatSupports(FormatFeatureFlags.FormatFeatureBlitDstBit, dstFormat))
|
||||||
{
|
{
|
||||||
TextureCopy.Blit(
|
TextureCopy.Blit(
|
||||||
_gd.Api,
|
_gd.Api,
|
||||||
@@ -761,8 +761,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private bool SupportsBlitFromD32FS8ToD32FAndS8()
|
private bool SupportsBlitFromD32FS8ToD32FAndS8()
|
||||||
{
|
{
|
||||||
var formatFeatureFlags = FormatFeatureFlags.FormatFeatureBlitSrcBit | FormatFeatureFlags.FormatFeatureBlitDstBit;
|
var formatFeatureFlags = FormatFeatureFlags.FormatFeatureBlitSrcBit | FormatFeatureFlags.FormatFeatureBlitDstBit;
|
||||||
return _gd.FormatCapabilities.FormatSupports(formatFeatureFlags, GAL.Format.D32Float) &&
|
return _gd.FormatCapabilities.OptimalFormatSupports(formatFeatureFlags, GAL.Format.D32Float) &&
|
||||||
_gd.FormatCapabilities.FormatSupports(formatFeatureFlags, GAL.Format.S8Uint);
|
_gd.FormatCapabilities.OptimalFormatSupports(formatFeatureFlags, GAL.Format.S8Uint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextureView GetView(GAL.Format format)
|
public TextureView GetView(GAL.Format format)
|
||||||
|
@@ -7,5 +7,6 @@
|
|||||||
public const bool UsePushDescriptors = false;
|
public const bool UsePushDescriptors = false;
|
||||||
|
|
||||||
public const bool ForceD24S8Unsupported = false;
|
public const bool ForceD24S8Unsupported = false;
|
||||||
|
public const bool ForceRGB16IntFloatUnsupported = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -377,7 +377,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
FormatFeatureFlags.FormatFeatureTransferSrcBit |
|
FormatFeatureFlags.FormatFeatureTransferSrcBit |
|
||||||
FormatFeatureFlags.FormatFeatureTransferDstBit;
|
FormatFeatureFlags.FormatFeatureTransferDstBit;
|
||||||
|
|
||||||
bool supportsBc123CompressionFormat = FormatCapabilities.FormatsSupports(compressedFormatFeatureFlags,
|
bool supportsBc123CompressionFormat = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags,
|
||||||
GAL.Format.Bc1RgbaSrgb,
|
GAL.Format.Bc1RgbaSrgb,
|
||||||
GAL.Format.Bc1RgbaUnorm,
|
GAL.Format.Bc1RgbaUnorm,
|
||||||
GAL.Format.Bc2Srgb,
|
GAL.Format.Bc2Srgb,
|
||||||
@@ -385,13 +385,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
GAL.Format.Bc3Srgb,
|
GAL.Format.Bc3Srgb,
|
||||||
GAL.Format.Bc3Unorm);
|
GAL.Format.Bc3Unorm);
|
||||||
|
|
||||||
bool supportsBc45CompressionFormat = FormatCapabilities.FormatsSupports(compressedFormatFeatureFlags,
|
bool supportsBc45CompressionFormat = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags,
|
||||||
GAL.Format.Bc4Snorm,
|
GAL.Format.Bc4Snorm,
|
||||||
GAL.Format.Bc4Unorm,
|
GAL.Format.Bc4Unorm,
|
||||||
GAL.Format.Bc5Snorm,
|
GAL.Format.Bc5Snorm,
|
||||||
GAL.Format.Bc5Unorm);
|
GAL.Format.Bc5Unorm);
|
||||||
|
|
||||||
bool supportsBc67CompressionFormat = FormatCapabilities.FormatsSupports(compressedFormatFeatureFlags,
|
bool supportsBc67CompressionFormat = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags,
|
||||||
GAL.Format.Bc6HSfloat,
|
GAL.Format.Bc6HSfloat,
|
||||||
GAL.Format.Bc6HUfloat,
|
GAL.Format.Bc6HUfloat,
|
||||||
GAL.Format.Bc7Srgb,
|
GAL.Format.Bc7Srgb,
|
||||||
|
@@ -154,9 +154,9 @@ namespace Ryujinx.Ui.Widgets
|
|||||||
//
|
//
|
||||||
// _purgePtcCacheMenuItem
|
// _purgePtcCacheMenuItem
|
||||||
//
|
//
|
||||||
_purgePtcCacheMenuItem = new MenuItem("Purge PPTC Cache")
|
_purgePtcCacheMenuItem = new MenuItem("Queue PPTC Rebuild")
|
||||||
{
|
{
|
||||||
TooltipText = "Delete the Application's PPTC cache."
|
TooltipText = "Trigger PPTC to rebuild at boot time on the next game launch."
|
||||||
};
|
};
|
||||||
_purgePtcCacheMenuItem.Activated += PurgePtcCache_Clicked;
|
_purgePtcCacheMenuItem.Activated += PurgePtcCache_Clicked;
|
||||||
|
|
||||||
|
@@ -522,7 +522,7 @@ namespace Ryujinx.Ui.Widgets
|
|||||||
DirectoryInfo mainDir = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "0"));
|
DirectoryInfo mainDir = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "0"));
|
||||||
DirectoryInfo backupDir = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "1"));
|
DirectoryInfo backupDir = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleIdText, "cache", "cpu", "1"));
|
||||||
|
|
||||||
MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to delete the PPTC cache for :\n\n<b>{_titleName}</b>\n\nAre you sure you want to proceed?");
|
MessageDialog warningDialog = GtkDialog.CreateConfirmationDialog("Warning", $"You are about to queue a PPTC rebuild on the next boot of:\n\n<b>{_titleName}</b>\n\nAre you sure you want to proceed?");
|
||||||
|
|
||||||
List<FileInfo> cacheFiles = new List<FileInfo>();
|
List<FileInfo> cacheFiles = new List<FileInfo>();
|
||||||
|
|
||||||
|
@@ -34,6 +34,7 @@ namespace Ryujinx.Ui.Windows
|
|||||||
|
|
||||||
private long _systemTimeOffset;
|
private long _systemTimeOffset;
|
||||||
private float _previousVolumeLevel;
|
private float _previousVolumeLevel;
|
||||||
|
private bool _directoryChanged = false;
|
||||||
|
|
||||||
#pragma warning disable CS0649, IDE0044
|
#pragma warning disable CS0649, IDE0044
|
||||||
[GUI] CheckButton _traceLogToggle;
|
[GUI] CheckButton _traceLogToggle;
|
||||||
@@ -500,10 +501,13 @@ namespace Ryujinx.Ui.Windows
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void SaveSettings()
|
private void SaveSettings()
|
||||||
|
{
|
||||||
|
if (_directoryChanged)
|
||||||
{
|
{
|
||||||
List<string> gameDirs = new List<string>();
|
List<string> gameDirs = new List<string>();
|
||||||
|
|
||||||
_gameDirsBoxStore.GetIterFirst(out TreeIter treeIter);
|
_gameDirsBoxStore.GetIterFirst(out TreeIter treeIter);
|
||||||
|
|
||||||
for (int i = 0; i < _gameDirsBoxStore.IterNChildren(); i++)
|
for (int i = 0; i < _gameDirsBoxStore.IterNChildren(); i++)
|
||||||
{
|
{
|
||||||
gameDirs.Add((string)_gameDirsBoxStore.GetValue(treeIter, 0));
|
gameDirs.Add((string)_gameDirsBoxStore.GetValue(treeIter, 0));
|
||||||
@@ -511,6 +515,11 @@ namespace Ryujinx.Ui.Windows
|
|||||||
_gameDirsBoxStore.IterNext(ref treeIter);
|
_gameDirsBoxStore.IterNext(ref treeIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs;
|
||||||
|
|
||||||
|
_directoryChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!float.TryParse(_resScaleText.Buffer.Text, out float resScaleCustom) || resScaleCustom <= 0.0f)
|
if (!float.TryParse(_resScaleText.Buffer.Text, out float resScaleCustom) || resScaleCustom <= 0.0f)
|
||||||
{
|
{
|
||||||
resScaleCustom = 1.0f;
|
resScaleCustom = 1.0f;
|
||||||
@@ -571,7 +580,6 @@ namespace Ryujinx.Ui.Windows
|
|||||||
ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset;
|
ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset;
|
||||||
ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text;
|
ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text;
|
||||||
ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text;
|
ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text;
|
||||||
ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs;
|
|
||||||
ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value;
|
ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value;
|
||||||
ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId, CultureInfo.InvariantCulture);
|
ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId, CultureInfo.InvariantCulture);
|
||||||
ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse<AspectRatio>(_aspectRatio.ActiveId);
|
ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse<AspectRatio>(_aspectRatio.ActiveId);
|
||||||
@@ -655,27 +663,27 @@ namespace Ryujinx.Ui.Windows
|
|||||||
|
|
||||||
if (fileChooser.Run() == (int)ResponseType.Accept)
|
if (fileChooser.Run() == (int)ResponseType.Accept)
|
||||||
{
|
{
|
||||||
|
_directoryChanged = false;
|
||||||
foreach (string directory in fileChooser.Filenames)
|
foreach (string directory in fileChooser.Filenames)
|
||||||
{
|
{
|
||||||
bool directoryAdded = false;
|
|
||||||
|
|
||||||
if (_gameDirsBoxStore.GetIterFirst(out TreeIter treeIter))
|
if (_gameDirsBoxStore.GetIterFirst(out TreeIter treeIter))
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (directory.Equals((string)_gameDirsBoxStore.GetValue(treeIter, 0)))
|
if (directory.Equals((string)_gameDirsBoxStore.GetValue(treeIter, 0)))
|
||||||
{
|
{
|
||||||
directoryAdded = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(_gameDirsBoxStore.IterNext(ref treeIter));
|
} while(_gameDirsBoxStore.IterNext(ref treeIter));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!directoryAdded)
|
if (!_directoryChanged)
|
||||||
{
|
{
|
||||||
_gameDirsBoxStore.AppendValues(directory);
|
_gameDirsBoxStore.AppendValues(directory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_directoryChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileChooser.Dispose();
|
fileChooser.Dispose();
|
||||||
@@ -693,6 +701,8 @@ namespace Ryujinx.Ui.Windows
|
|||||||
if (selection.GetSelected(out TreeIter treeIter))
|
if (selection.GetSelected(out TreeIter treeIter))
|
||||||
{
|
{
|
||||||
_gameDirsBoxStore.Remove(ref treeIter);
|
_gameDirsBoxStore.Remove(ref treeIter);
|
||||||
|
|
||||||
|
_directoryChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
|
((ToggleButton)sender).SetStateFlags(StateFlags.Normal, true);
|
||||||
|
Reference in New Issue
Block a user