diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs index e4cd63d61..9123f0443 100644 --- a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs +++ b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs @@ -19,10 +19,15 @@ namespace Ryujinx.Configuration /// /// The current version of the file format /// - public const int CurrentVersion = 3; + public const int CurrentVersion = 4; public int Version { get; set; } + /// + /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. + /// + public float MaxAnisotropy { get; set; } + /// /// Dumps shaders in this local directory /// diff --git a/Ryujinx.Common/Configuration/ConfigurationState.cs b/Ryujinx.Common/Configuration/ConfigurationState.cs index e563008ac..67628aa13 100644 --- a/Ryujinx.Common/Configuration/ConfigurationState.cs +++ b/Ryujinx.Common/Configuration/ConfigurationState.cs @@ -235,6 +235,11 @@ namespace Ryujinx.Configuration /// public class GraphicsSection { + /// + /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. + /// + public ReactiveObject MaxAnisotropy { get; private set; } + /// /// Dumps shaders in this local directory /// @@ -247,6 +252,7 @@ namespace Ryujinx.Configuration public GraphicsSection() { + MaxAnisotropy = new ReactiveObject(); ShadersDumpPath = new ReactiveObject(); EnableVsync = new ReactiveObject(); } @@ -302,6 +308,7 @@ namespace Ryujinx.Configuration ConfigurationFileFormat configurationFile = new ConfigurationFileFormat { Version = ConfigurationFileFormat.CurrentVersion, + MaxAnisotropy = Graphics.MaxAnisotropy, GraphicsShadersDumpPath = Graphics.ShadersDumpPath, LoggingEnableDebug = Logger.EnableDebug, LoggingEnableStub = Logger.EnableStub, @@ -349,6 +356,7 @@ namespace Ryujinx.Configuration public void LoadDefault() { + Graphics.MaxAnisotropy.Value = -1; Graphics.ShadersDumpPath.Value = ""; Logger.EnableDebug.Value = false; Logger.EnableStub.Value = true; @@ -487,6 +495,16 @@ namespace Ryujinx.Configuration configurationFileUpdated = true; } + if (configurationFileFormat.Version < 4) + { + Common.Logging.Logger.PrintWarning(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4."); + + configurationFileFormat.MaxAnisotropy = -1; + + configurationFileUpdated = true; + } + + Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy; Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath; Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug; Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub; diff --git a/Ryujinx.Graphics.GAL/Capabilities.cs b/Ryujinx.Graphics.GAL/Capabilities.cs index b75ceb94f..8ea4c02aa 100644 --- a/Ryujinx.Graphics.GAL/Capabilities.cs +++ b/Ryujinx.Graphics.GAL/Capabilities.cs @@ -8,16 +8,20 @@ namespace Ryujinx.Graphics.GAL public int MaximumComputeSharedMemorySize { get; } public int StorageBufferOffsetAlignment { get; } + public float MaxSupportedAnisotropy { get; } + public Capabilities( - bool supportsAstcCompression, - bool supportsNonConstantTextureOffset, - int maximumComputeSharedMemorySize, - int storageBufferOffsetAlignment) + bool supportsAstcCompression, + bool supportsNonConstantTextureOffset, + int maximumComputeSharedMemorySize, + int storageBufferOffsetAlignment, + float maxSupportedAnisotropy) { SupportsAstcCompression = supportsAstcCompression; SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset; MaximumComputeSharedMemorySize = maximumComputeSharedMemorySize; StorageBufferOffsetAlignment = storageBufferOffsetAlignment; + MaxSupportedAnisotropy = maxSupportedAnisotropy; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/GraphicsConfig.cs b/Ryujinx.Graphics.Gpu/GraphicsConfig.cs index 468d3a342..4bda7c19c 100644 --- a/Ryujinx.Graphics.Gpu/GraphicsConfig.cs +++ b/Ryujinx.Graphics.Gpu/GraphicsConfig.cs @@ -5,6 +5,11 @@ namespace Ryujinx.Graphics.Gpu /// public static class GraphicsConfig { + /// + /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. + /// + public static float MaxAnisotropy; + /// /// Base directory used to write shader code dumps. /// Set to null to disable code dumping. diff --git a/Ryujinx.Graphics.Gpu/Image/Sampler.cs b/Ryujinx.Graphics.Gpu/Image/Sampler.cs index 45f5f519f..827d6077f 100644 --- a/Ryujinx.Graphics.Gpu/Image/Sampler.cs +++ b/Ryujinx.Graphics.Gpu/Image/Sampler.cs @@ -40,7 +40,11 @@ namespace Ryujinx.Graphics.Gpu.Image float maxLod = descriptor.UnpackMaxLod(); float mipLodBias = descriptor.UnpackMipLodBias(); - float maxAnisotropy = descriptor.UnpackMaxAnisotropy(); + float maxRequestedAnisotropy = GraphicsConfig.MaxAnisotropy >= 0 && GraphicsConfig.MaxAnisotropy <= 16 ? GraphicsConfig.MaxAnisotropy : descriptor.UnpackMaxAnisotropy(); + float maxSupportedAnisotropy = context.Capabilities.MaxSupportedAnisotropy; + + if (maxRequestedAnisotropy > maxSupportedAnisotropy) + maxRequestedAnisotropy = maxSupportedAnisotropy; HostSampler = context.Renderer.CreateSampler(new SamplerCreateInfo( minFilter, @@ -54,7 +58,7 @@ namespace Ryujinx.Graphics.Gpu.Image minLod, maxLod, mipLodBias, - maxAnisotropy)); + maxRequestedAnisotropy)); } /// diff --git a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs index 3d72cb7da..4b572af82 100644 --- a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs +++ b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs @@ -22,12 +22,16 @@ namespace Ryujinx.Graphics.OpenGL public static GpuVendor Vendor => _gpuVendor.Value; + private static Lazy _maxSupportedAnisotropy = new Lazy(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy)); + public static bool SupportsAstcCompression => _supportsAstcCompression.Value; public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia; public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value; public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value; + public static float MaxSupportedAnisotropy => _maxSupportedAnisotropy.Value; + private static bool HasExtension(string name) { int numExtensions = GL.GetInteger(GetPName.NumExtensions); diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs index cf2adc45c..504a947be 100644 --- a/Ryujinx.Graphics.OpenGL/Renderer.cs +++ b/Ryujinx.Graphics.OpenGL/Renderer.cs @@ -67,7 +67,8 @@ namespace Ryujinx.Graphics.OpenGL HwCapabilities.SupportsAstcCompression, HwCapabilities.SupportsNonConstantTextureOffset, HwCapabilities.MaximumComputeSharedMemorySize, - HwCapabilities.StorageBufferOffsetAlignment); + HwCapabilities.StorageBufferOffsetAlignment, + HwCapabilities.MaxSupportedAnisotropy); } public ulong GetCounter(CounterType type) diff --git a/Ryujinx/Config.json b/Ryujinx/Config.json index 80430899f..8a3655501 100644 --- a/Ryujinx/Config.json +++ b/Ryujinx/Config.json @@ -1,5 +1,6 @@ { - "version": 2, + "version": 4, + "max_anisotropy": -1, "graphics_shaders_dump_path": "", "logging_enable_debug": false, "logging_enable_stub": true, @@ -12,6 +13,7 @@ "enable_file_log": true, "system_language": "AmericanEnglish", "system_region": "USA", + "system_time_zone": "UTC", "docked_mode": false, "enable_discord_integration": true, "enable_vsync": true, diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index e6c632d95..16438ecc6 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -308,6 +308,7 @@ namespace Ryujinx.Ui HLE.Switch device = InitializeSwitchInstance(); // TODO: Move this somewhere else + reloadable? + Graphics.Gpu.GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy; Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; if (Directory.Exists(path)) diff --git a/Ryujinx/Ui/SwitchSettings.cs b/Ryujinx/Ui/SwitchSettings.cs index 777313a1c..8ff404278 100644 --- a/Ryujinx/Ui/SwitchSettings.cs +++ b/Ryujinx/Ui/SwitchSettings.cs @@ -52,6 +52,7 @@ namespace Ryujinx.Ui [GUI] ToggleButton _browseDir; [GUI] ToggleButton _removeDir; [GUI] Entry _graphicsShadersDumpPath; + [GUI] ComboBoxText _anisotropy; [GUI] Image _controller1Image; [GUI] ComboBoxText _controller1Type; @@ -215,6 +216,7 @@ namespace Ryujinx.Ui _systemLanguageSelect.SetActiveId(ConfigurationState.Instance.System.Language.Value.ToString()); _systemRegionSelect .SetActiveId(ConfigurationState.Instance.System.Region.Value.ToString()); _systemTimeZoneSelect.SetActiveId(timeZoneContentManager.SanityCheckDeviceLocationName()); + _anisotropy .SetActiveId(ConfigurationState.Instance.Graphics.MaxAnisotropy.Value.ToString()); _controller1Type .SetActiveId(ConfigurationState.Instance.Hid.ControllerType.Value.ToString()); Controller_Changed(null, null, _controller1Type.ActiveId, _controller1Image); @@ -458,6 +460,7 @@ namespace Ryujinx.Ui ConfigurationState.Instance.System.Language.Value = (Language)Enum.Parse(typeof(Language), _systemLanguageSelect.ActiveId); ConfigurationState.Instance.System.Region.Value = (Configuration.System.Region)Enum.Parse(typeof(Configuration.System.Region), _systemRegionSelect.ActiveId); + ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId); ConfigurationState.Instance.Hid.ControllerType.Value = (ControllerType)Enum.Parse(typeof(ControllerType), _controller1Type.ActiveId); ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text; ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text; diff --git a/Ryujinx/Ui/SwitchSettings.glade b/Ryujinx/Ui/SwitchSettings.glade index fc9413ec0..7c9346391 100644 --- a/Ryujinx/Ui/SwitchSettings.glade +++ b/Ryujinx/Ui/SwitchSettings.glade @@ -177,8 +177,8 @@ False True - 2 5 + 2 @@ -247,6 +247,11 @@ + + False + True + 0 + @@ -1452,6 +1457,52 @@ + + False + True + 5 + 3 + + + + + True + False + + + True + False + Graphics Shaders Dump Path + Anisotropic Filtering: + + + False + True + 5 + 0 + + + + + True + False + Change System TimeZone + -1 + + Auto + 2x + 4x + 8x + 16x + + + + False + True + 1 + + + False True