diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs | 118 |
1 files changed, 46 insertions, 72 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs index 7ec4c7ac..e8061951 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs @@ -380,42 +380,37 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> /// <param name="lhs">Texture information of the texture view</param> /// <param name="rhs">Texture information of the texture view to match against</param> + /// <param name="exact">Indicates if the sizes must be exactly equal</param> /// <param name="level">Mipmap level of the texture view in relation to this texture</param> /// <returns>The view compatibility level of the view sizes</returns> - public static TextureViewCompatibility ViewSizeMatches(TextureInfo lhs, TextureInfo rhs, int level) + public static TextureViewCompatibility ViewSizeMatches(TextureInfo lhs, TextureInfo rhs, bool exact, int level) { - Size size = GetAlignedSize(lhs, level); + Size lhsAlignedSize = GetAlignedSize(lhs, level); + Size rhsAlignedSize = GetAlignedSize(rhs); - Size otherSize = GetAlignedSize(rhs); + Size lhsSize = GetSizeInBlocks(lhs, level); + Size rhsSize = GetSizeInBlocks(rhs); TextureViewCompatibility result = TextureViewCompatibility.Full; // For copies, we can copy a subset of the 3D texture slices, // so the depth may be different in this case. - if (rhs.Target == Target.Texture3D && size.Depth != otherSize.Depth) + if (rhs.Target == Target.Texture3D && lhsSize.Depth != rhsSize.Depth) { result = TextureViewCompatibility.CopyOnly; } - if (size.Width == otherSize.Width && size.Height == otherSize.Height) + // Some APIs align the width for copy and render target textures, + // so the width may not match in this case for different uses of the same texture. + // To account for this, we compare the aligned width here. + // We expect height to always match exactly, if the texture is the same. + if (lhsAlignedSize.Width == rhsAlignedSize.Width && lhsSize.Height == rhsSize.Height) { - if (level > 0 && result == TextureViewCompatibility.Full) - { - // A resize should not change the aligned size of the largest mip. - // If it would, then create a copy dependency rather than a full view. - - Size mip0SizeLhs = GetAlignedSize(lhs); - Size mip0SizeRhs = GetLargestAlignedSize(rhs, level); - - if (mip0SizeLhs.Width != mip0SizeRhs.Width || mip0SizeLhs.Height != mip0SizeRhs.Height) - { - result = TextureViewCompatibility.CopyOnly; - } - } - - return result; + return (exact && lhsSize.Width != rhsSize.Width) || lhsSize.Width < rhsSize.Width + ? TextureViewCompatibility.CopyOnly + : result; } - else if (lhs.IsLinear && rhs.IsLinear) + else if (lhs.IsLinear && rhs.IsLinear && lhsSize.Height == rhsSize.Height) { // Copy between linear textures with matching stride. int stride = BitUtils.AlignUp(Math.Max(1, lhs.Stride >> level), Constants.StrideAlignment); @@ -454,57 +449,33 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> /// <param name="lhs">Texture information to compare</param> /// <param name="rhs">Texture information to compare with</param> - /// <returns>True if the size matches, false otherwise</returns> - public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs) - { - return SizeMatches(lhs, rhs, alignSizes: false); - } - - /// <summary> - /// Checks if the texture sizes of the supplied texture informations match the given level - /// </summary> - /// <param name="lhs">Texture information to compare</param> - /// <param name="rhs">Texture information to compare with</param> - /// <param name="level">Mipmap level of this texture to compare with</param> - /// <returns>True if the size matches with the level, false otherwise</returns> - public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, int level) - { - return Math.Max(1, lhs.Width >> level) == rhs.Width && - Math.Max(1, lhs.Height >> level) == rhs.Height && - Math.Max(1, lhs.GetDepth() >> level) == rhs.GetDepth(); - } - - /// <summary> - /// Checks if the texture sizes of the supplied texture informations match. - /// </summary> - /// <param name="lhs">Texture information to compare</param> - /// <param name="rhs">Texture information to compare with</param> - /// <param name="alignSizes">True to align the sizes according to the texture layout for comparison</param> - /// <param name="lhsLevel">Mip level of the lhs texture. Aligned sizes are compared for the largest mip</param> + /// <param name="exact">Indicates if the size must be exactly equal between the textures, or if <paramref name="rhs"/> is allowed to be larger</param> /// <returns>True if the sizes matches, false otherwise</returns> - public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, bool alignSizes, int lhsLevel = 0) + public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, bool exact) { if (lhs.GetLayers() != rhs.GetLayers()) { return false; } - bool isTextureBuffer = lhs.Target == Target.TextureBuffer || rhs.Target == Target.TextureBuffer; + Size lhsSize = GetSizeInBlocks(lhs); + Size rhsSize = GetSizeInBlocks(rhs); - if (alignSizes && !isTextureBuffer) + if (exact || lhs.IsLinear || rhs.IsLinear) { - Size size0 = GetLargestAlignedSize(lhs, lhsLevel); - Size size1 = GetLargestAlignedSize(rhs, lhsLevel); - - return size0.Width == size1.Width && - size0.Height == size1.Height && - size0.Depth == size1.Depth; + return lhsSize.Width == rhsSize.Width && + lhsSize.Height == rhsSize.Height && + lhsSize.Depth == rhsSize.Depth; } else { - return lhs.Width == rhs.Width && - lhs.Height == rhs.Height && - lhs.GetDepth() == rhs.GetDepth(); + Size lhsAlignedSize = GetAlignedSize(lhs); + Size rhsAlignedSize = GetAlignedSize(rhs); + + return lhsAlignedSize.Width == rhsAlignedSize.Width && + lhsSize.Width >= rhsSize.Width && + lhsSize.Height == rhsSize.Height && + lhsSize.Depth == rhsSize.Depth; } } @@ -544,35 +515,38 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> - /// Gets the aligned sizes of the specified texture information, shifted to the largest mip from a given level. + /// Gets the aligned sizes of the specified texture information. /// The alignment depends on the texture layout and format bytes per pixel. /// </summary> /// <param name="info">Texture information to calculate the aligned size from</param> - /// <param name="level">Mipmap level for texture views. Shifts the aligned size to represent the largest mip level</param> - /// <returns>The aligned texture size of the largest mip level</returns> - public static Size GetLargestAlignedSize(TextureInfo info, int level) + /// <param name="level">Mipmap level for texture views</param> + /// <returns>The aligned texture size</returns> + public static Size GetAlignedSize(TextureInfo info, int level = 0) { - int width = info.Width << level; - int height = info.Height << level; - int depth = info.GetDepth() << level; + int width = Math.Max(1, info.Width >> level); + int height = Math.Max(1, info.Height >> level); + int depth = Math.Max(1, info.GetDepth() >> level); return GetAlignedSize(info, width, height, depth); } /// <summary> - /// Gets the aligned sizes of the specified texture information. - /// The alignment depends on the texture layout and format bytes per pixel. + /// Gets the size in blocks for the given texture information. + /// For non-compressed formats, that's the same as the regular size. /// </summary> /// <param name="info">Texture information to calculate the aligned size from</param> /// <param name="level">Mipmap level for texture views</param> - /// <returns>The aligned texture size</returns> - public static Size GetAlignedSize(TextureInfo info, int level = 0) + /// <returns>The texture size in blocks</returns> + public static Size GetSizeInBlocks(TextureInfo info, int level = 0) { int width = Math.Max(1, info.Width >> level); int height = Math.Max(1, info.Height >> level); int depth = Math.Max(1, info.GetDepth() >> level); - return GetAlignedSize(info, width, height, depth); + return new Size( + BitUtils.DivRoundUp(width, info.FormatInfo.BlockWidth), + BitUtils.DivRoundUp(height, info.FormatInfo.BlockHeight), + depth); } /// <summary> |