From 4f75e26ec7e61e606f812bd0149eef69bdc8a4ea Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 12 Aug 2024 17:45:25 -0300 Subject: [PATCH 1/2] Clamp amount of mipmap levels to max allowed for all backends (#7197) * Clamp amount of mipmap levels to max allowed for all backends * XML docs * Remove using --- src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs | 20 ------------ src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs | 31 +++++++++++++++++++ .../Image/TextureStorage.cs | 2 +- .../Image/TextureView.cs | 8 ++--- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs b/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs index 44090291dd..79c84db016 100644 --- a/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs +++ b/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs @@ -1,6 +1,5 @@ using Ryujinx.Common; using System; -using System.Numerics; namespace Ryujinx.Graphics.GAL { @@ -113,25 +112,6 @@ namespace Ryujinx.Graphics.GAL return 1; } - public int GetLevelsClamped() - { - int maxSize = Width; - - if (Target != Target.Texture1D && - Target != Target.Texture1DArray) - { - maxSize = Math.Max(maxSize, Height); - } - - if (Target == Target.Texture3D) - { - maxSize = Math.Max(maxSize, Depth); - } - - int maxLevels = BitOperations.Log2((uint)maxSize) + 1; - return Math.Min(Levels, maxLevels); - } - private static int GetLevelSize(int size, int level) { return Math.Max(1, size >> level); diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index a4035577d3..4ed0a93c17 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs @@ -6,6 +6,7 @@ using Ryujinx.Memory.Range; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Numerics; using System.Threading; namespace Ryujinx.Graphics.Gpu.Image @@ -490,6 +491,8 @@ namespace Ryujinx.Graphics.Gpu.Image levels = (maxLod - minLod) + 1; } + levels = ClampLevels(target, width, height, depthOrLayers, levels); + SwizzleComponent swizzleR = descriptor.UnpackSwizzleR().Convert(); SwizzleComponent swizzleG = descriptor.UnpackSwizzleG().Convert(); SwizzleComponent swizzleB = descriptor.UnpackSwizzleB().Convert(); @@ -540,6 +543,34 @@ namespace Ryujinx.Graphics.Gpu.Image swizzleA); } + /// + /// Clamps the amount of mipmap levels to the maximum allowed for the given texture dimensions. + /// + /// Number of texture dimensions (1D, 2D, 3D, Cube, etc) + /// Width of the texture + /// Height of the texture, ignored for 1D textures + /// Depth of the texture for 3D textures, otherwise ignored + /// Original amount of mipmap levels + /// Clamped mipmap levels + private static int ClampLevels(Target target, int width, int height, int depthOrLayers, int levels) + { + int maxSize = width; + + if (target != Target.Texture1D && + target != Target.Texture1DArray) + { + maxSize = Math.Max(maxSize, height); + } + + if (target == Target.Texture3D) + { + maxSize = Math.Max(maxSize, depthOrLayers); + } + + int maxLevels = BitOperations.Log2((uint)maxSize) + 1; + return Math.Min(levels, maxLevels); + } + /// /// Gets the texture depth-stencil mode, based on the swizzle components of each color channel. /// The depth-stencil mode is determined based on how the driver sets those parameters. diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs index 79c6cb685b..0ebafb04e9 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs @@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.OpenGL.Image internalFormat = (SizedInternalFormat)format.PixelInternalFormat; } - int levels = Info.GetLevelsClamped(); + int levels = Info.Levels; switch (Info.Target) { diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs index 8a18e6132a..946eb755cc 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs @@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.OpenGL.Image pixelInternalFormat = format.PixelInternalFormat; } - int levels = Info.GetLevelsClamped(); + int levels = Info.Levels; GL.TextureView( Handle, @@ -267,7 +267,7 @@ namespace Ryujinx.Graphics.OpenGL.Image public unsafe PinnedSpan GetData() { int size = 0; - int levels = Info.GetLevelsClamped(); + int levels = Info.Levels; for (int level = 0; level < levels; level++) { @@ -426,7 +426,7 @@ namespace Ryujinx.Graphics.OpenGL.Image faces = 6; } - int levels = Info.GetLevelsClamped(); + int levels = Info.Levels; for (int level = 0; level < levels; level++) { @@ -716,7 +716,7 @@ namespace Ryujinx.Graphics.OpenGL.Image int width = Info.Width; int height = Info.Height; int depth = Info.Depth; - int levels = Info.GetLevelsClamped(); + int levels = Info.Levels; int offset = 0; From 23fa5f4c9c0ee865dd0a4def3be1822e598c9a91 Mon Sep 17 00:00:00 2001 From: Logan Stromberg Date: Tue, 13 Aug 2024 06:23:11 -0700 Subject: [PATCH 2/2] Fix arbitrary game ordering when sorting by Favorites (#7170) * Fix arbitrary sorting by "Favorite" in the UI by making it the same as sorting alphabetically while giving favorites priority. * Use a more engineered solution rather than string hacks. * Address code style warnings. Add null checking. Make title name comparison case insensitive. * one more style fix --------- Co-authored-by: Logan Stromberg --- .../ViewModels/AppListFavoriteComparable.cs | 43 +++++++++++++++++++ .../UI/ViewModels/MainWindowViewModel.cs | 4 +- 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/Ryujinx/UI/ViewModels/AppListFavoriteComparable.cs diff --git a/src/Ryujinx/UI/ViewModels/AppListFavoriteComparable.cs b/src/Ryujinx/UI/ViewModels/AppListFavoriteComparable.cs new file mode 100644 index 0000000000..e80984508e --- /dev/null +++ b/src/Ryujinx/UI/ViewModels/AppListFavoriteComparable.cs @@ -0,0 +1,43 @@ +using Ryujinx.UI.App.Common; +using System; + +namespace Ryujinx.Ava.UI.ViewModels +{ + /// + /// Implements a custom comparer which is used for sorting titles by favorite on a UI. + /// Returns a sorted list of favorites in alphabetical order, followed by all non-favorites sorted alphabetical. + /// + public readonly struct AppListFavoriteComparable : IComparable + { + /// + /// The application data being compared. + /// + private readonly ApplicationData app; + + /// + /// Constructs a new with the specified application data. + /// + /// The app data being compared. + public AppListFavoriteComparable(ApplicationData app) + { + ArgumentNullException.ThrowIfNull(app, nameof(app)); + this.app = app; + } + + /// + public readonly int CompareTo(object o) + { + if (o is AppListFavoriteComparable other) + { + if (app.Favorite == other.app.Favorite) + { + return string.Compare(app.Name, other.app.Name, StringComparison.OrdinalIgnoreCase); + } + + return app.Favorite ? -1 : 1; + } + + throw new InvalidCastException($"Cannot cast {o.GetType()} to {nameof(AppListFavoriteComparable)}"); + } + } +} diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 134e903002..bd9f165b92 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -965,8 +965,8 @@ namespace Ryujinx.Ava.UI.ViewModels : SortExpressionComparer.Descending(app => app.FileSize), ApplicationSort.Path => IsAscending ? SortExpressionComparer.Ascending(app => app.Path) : SortExpressionComparer.Descending(app => app.Path), - ApplicationSort.Favorite => !IsAscending ? SortExpressionComparer.Ascending(app => app.Favorite) - : SortExpressionComparer.Descending(app => app.Favorite), + ApplicationSort.Favorite => IsAscending ? SortExpressionComparer.Ascending(app => new AppListFavoriteComparable(app)) + : SortExpressionComparer.Descending(app => new AppListFavoriteComparable(app)), _ => null, #pragma warning restore IDE0055 };