Browse Source

Improve linear texture compatibility rules (#2099)

* Improve linear texture compatibility rules

Fixes an issue where small or width-aligned (rather than byte aligned) textures would fail to create a view of existing data. Creates a copy dependency as size change may be risky.

* Minor cleanup

* Remove Size Change for Copy Depenedencies

The copy to the target (potentially different sized) texture can properly deal with cropping by itself.

* Move StrideAlignment and GobAlignment into Constants
riperiperi 5 years ago
parent
commit
9b7335a63b

+ 10 - 0
Ryujinx.Graphics.Gpu/Constants.cs

@@ -69,5 +69,15 @@ namespace Ryujinx.Graphics.Gpu
         /// Maximum size of gl_ClipDistance array in shaders.
         /// Maximum size of gl_ClipDistance array in shaders.
         /// </summary>
         /// </summary>
         public const int TotalClipDistances = 8;
         public const int TotalClipDistances = 8;
+
+        /// <summary>
+        /// Byte alignment for texture stride.
+        /// </summary>
+        public const int StrideAlignment = 32;
+
+        /// <summary>
+        /// Byte alignment for block linear textures
+        /// </summary>
+        public const int GobAlignment = 64;
     }
     }
 }
 }

+ 2 - 5
Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs

@@ -8,9 +8,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
 {
 {
     partial class Methods
     partial class Methods
     {
     {
-        private const int StrideAlignment = 32;
-        private const int GobAlignment = 64;
-
         enum CopyFlags
         enum CopyFlags
         {
         {
             SrcLinear = 1 << 7,
             SrcLinear = 1 << 7,
@@ -32,14 +29,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
         {
         {
             if (linear)
             if (linear)
             {
             {
-                int alignWidth = StrideAlignment / bpp;
+                int alignWidth = Constants.StrideAlignment / bpp;
                 return tex.RegionX == 0 &&
                 return tex.RegionX == 0 &&
                        tex.RegionY == 0 &&
                        tex.RegionY == 0 &&
                        stride / bpp == BitUtils.AlignUp(cbp.XCount, alignWidth);
                        stride / bpp == BitUtils.AlignUp(cbp.XCount, alignWidth);
             }
             }
             else
             else
             {
             {
-                int alignWidth = GobAlignment / bpp;
+                int alignWidth = Constants.GobAlignment / bpp;
                 return tex.RegionX == 0 &&
                 return tex.RegionX == 0 &&
                        tex.RegionY == 0 &&
                        tex.RegionY == 0 &&
                        tex.Width == BitUtils.AlignUp(cbp.XCount, alignWidth) &&
                        tex.Width == BitUtils.AlignUp(cbp.XCount, alignWidth) &&

+ 16 - 4
Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs

@@ -231,8 +231,21 @@ namespace Ryujinx.Graphics.Gpu.Image
                 result = TextureViewCompatibility.CopyOnly;
                 result = TextureViewCompatibility.CopyOnly;
             }
             }
 
 
-            return (size.Width  == otherSize.Width &&
-                    size.Height == otherSize.Height) ? result : TextureViewCompatibility.Incompatible;
+            if (size.Width == otherSize.Width && size.Height == otherSize.Height)
+            {
+                return result;
+            }
+            else if (lhs.IsLinear && rhs.IsLinear)
+            {
+                // Copy between linear textures with matching stride.
+                int stride = BitUtils.AlignUp(Math.Max(1, lhs.Stride >> level), Constants.StrideAlignment);
+
+                return stride == rhs.Stride ? TextureViewCompatibility.CopyOnly : TextureViewCompatibility.Incompatible;
+            }
+            else
+            {
+                return TextureViewCompatibility.Incompatible;
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -372,8 +385,7 @@ namespace Ryujinx.Graphics.Gpu.Image
             // For block linear textures, the stride is ignored.
             // For block linear textures, the stride is ignored.
             if (rhs.IsLinear)
             if (rhs.IsLinear)
             {
             {
-                int width = Math.Max(1, lhs.Width >> level);
-                int stride = width * lhs.FormatInfo.BytesPerPixel;
+                int stride = Math.Max(1, lhs.Stride >> level);
                 stride = BitUtils.AlignUp(stride, 32);
                 stride = BitUtils.AlignUp(stride, 32);
 
 
                 return stride == rhs.Stride;
                 return stride == rhs.Stride;

+ 0 - 3
Ryujinx.Graphics.Gpu/Image/TextureGroup.cs

@@ -16,9 +16,6 @@ namespace Ryujinx.Graphics.Gpu.Image
     /// </summary>
     /// </summary>
     class TextureGroup : IDisposable
     class TextureGroup : IDisposable
     {
     {
-        private const int StrideAlignment = 32;
-        private const int GobAlignment = 64;
-
         private delegate void HandlesCallbackDelegate(int baseHandle, int regionCount, bool split = false);
         private delegate void HandlesCallbackDelegate(int baseHandle, int regionCount, bool split = false);
 
 
         /// <summary>
         /// <summary>

+ 1 - 3
Ryujinx.Graphics.Gpu/Image/TextureManager.cs

@@ -429,7 +429,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 // Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas)
                 // Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas)
                 // Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height.
                 // Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height.
 
 
-                int widthAlignment = (info.IsLinear ? 32 : 64) / info.FormatInfo.BytesPerPixel;
+                int widthAlignment = (info.IsLinear ? Constants.StrideAlignment : Constants.GobAlignment) / info.FormatInfo.BytesPerPixel;
 
 
                 bool possiblySquare = BitUtils.AlignUp(info.Width, widthAlignment) == BitUtils.AlignUp(info.Height, widthAlignment);
                 bool possiblySquare = BitUtils.AlignUp(info.Width, widthAlignment) == BitUtils.AlignUp(info.Height, widthAlignment);
 
 
@@ -977,8 +977,6 @@ namespace Ryujinx.Graphics.Gpu.Image
                     {
                     {
                         // Copy only compatibility, or target texture is already a view.
                         // Copy only compatibility, or target texture is already a view.
 
 
-                        ChangeSizeIfNeeded(overlapInfo, overlap, false, sizeHint); // Force a size match for copy
-
                         overlap.SynchronizeMemory();
                         overlap.SynchronizeMemory();
                         texture.CreateCopyDependency(overlap, oInfo.FirstLayer, oInfo.FirstLevel, false);
                         texture.CreateCopyDependency(overlap, oInfo.FirstLayer, oInfo.FirstLevel, false);
                     }
                     }