Преглед изворни кода

Fix texture level offset/size calculation when sparse tile width is > 1 (#1142)

* Fix texture level offset/size calculation when sparse tile width is > 1

* Sparse tile width affects layer size alignment aswell
gdkchan пре 6 година
родитељ
комит
34d19f381c

+ 2 - 9
Ryujinx.Graphics.Gpu/Image/Texture.cs

@@ -870,13 +870,6 @@ namespace Ryujinx.Graphics.Gpu.Image
             {
                 int depth = Math.Max(1, info.GetDepth() >> level);
 
-                (int gobBlocksInY, int gobBlocksInZ) = SizeCalculator.GetMipGobBlockSizes(
-                    height,
-                    depth,
-                    info.FormatInfo.BlockHeight,
-                    info.GobBlocksInY,
-                    info.GobBlocksInZ);
-
                 return SizeCalculator.GetBlockLinearAlignedSize(
                     width,
                     height,
@@ -884,8 +877,8 @@ namespace Ryujinx.Graphics.Gpu.Image
                     info.FormatInfo.BlockWidth,
                     info.FormatInfo.BlockHeight,
                     info.FormatInfo.BytesPerPixel,
-                    gobBlocksInY,
-                    gobBlocksInZ,
+                    info.GobBlocksInY,
+                    info.GobBlocksInZ,
                     info.GobBlocksInTileX);
             }
         }

+ 26 - 8
Ryujinx.Graphics.Texture/LayoutConverter.cs

@@ -38,11 +38,12 @@ namespace Ryujinx.Graphics.Texture
 
             int outOffs = 0;
 
-            int wAlignment = gobBlocksInTileX * (GobStride / bytesPerPixel);
-
             int mipGobBlocksInY = gobBlocksInY;
             int mipGobBlocksInZ = gobBlocksInZ;
 
+            int gobWidth  = (GobStride / bytesPerPixel) * gobBlocksInTileX;
+            int gobHeight = gobBlocksInY * GobHeight;
+
             for (int level = 0; level < levels; level++)
             {
                 int w = Math.Max(1, width  >> level);
@@ -66,8 +67,16 @@ namespace Ryujinx.Graphics.Texture
 
                 int xStart = strideTrunc / bytesPerPixel;
 
-                int stride   = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
-                int wAligned = BitUtils.AlignUp(w, wAlignment);
+                int stride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
+
+                int alignment = gobWidth;
+
+                if (d < gobBlocksInZ || w <= gobWidth || h <= gobHeight)
+                {
+                    alignment = GobStride / bytesPerPixel;
+                }
+
+                int wAligned = BitUtils.AlignUp(w, alignment);
 
                 BlockLinearLayout layoutConverter = new BlockLinearLayout(
                     wAligned,
@@ -164,11 +173,12 @@ namespace Ryujinx.Graphics.Texture
 
             int inOffs = 0;
 
-            int wAlignment = gobBlocksInTileX * (GobStride / bytesPerPixel);
-
             int mipGobBlocksInY = gobBlocksInY;
             int mipGobBlocksInZ = gobBlocksInZ;
 
+            int gobWidth  = (GobStride / bytesPerPixel) * gobBlocksInTileX;
+            int gobHeight = gobBlocksInY * GobHeight;
+
             for (int level = 0; level < levels; level++)
             {
                 int w = Math.Max(1, width  >> level);
@@ -188,8 +198,16 @@ namespace Ryujinx.Graphics.Texture
                     mipGobBlocksInZ >>= 1;
                 }
 
-                int stride   = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
-                int wAligned = BitUtils.AlignUp(w, wAlignment);
+                int stride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
+
+                int alignment = gobWidth;
+
+                if (d < gobBlocksInZ || w <= gobWidth || h <= gobHeight)
+                {
+                    alignment = GobStride / bytesPerPixel;
+                }
+
+                int wAligned = BitUtils.AlignUp(w, alignment);
 
                 BlockLinearLayout layoutConverter = new BlockLinearLayout(
                     wAligned,

+ 51 - 18
Ryujinx.Graphics.Texture/SizeCalculator.cs

@@ -32,6 +32,9 @@ namespace Ryujinx.Graphics.Texture
             int mipGobBlocksInY = gobBlocksInY;
             int mipGobBlocksInZ = gobBlocksInZ;
 
+            int gobWidth  = (GobStride / bytesPerPixel) * gobBlocksInTileX;
+            int gobHeight = gobBlocksInY * GobHeight;
+
             for (int level = 0; level < levels; level++)
             {
                 int w = Math.Max(1, width  >> level);
@@ -51,7 +54,16 @@ namespace Ryujinx.Graphics.Texture
                     mipGobBlocksInZ >>= 1;
                 }
 
-                int widthInGobs = BitUtils.AlignUp(BitUtils.DivRoundUp(w * bytesPerPixel, GobStride), gobBlocksInTileX);
+                int widthInGobs = BitUtils.DivRoundUp(w * bytesPerPixel, GobStride);
+
+                int alignment = gobBlocksInTileX;
+
+                if (d < gobBlocksInZ || w <= gobWidth || h <= gobHeight)
+                {
+                    alignment = 1;
+                }
+
+                widthInGobs = BitUtils.AlignUp(widthInGobs, alignment);
 
                 int totalBlocksOfGobsInZ = BitUtils.DivRoundUp(d, mipGobBlocksInZ);
                 int totalBlocksOfGobsInY = BitUtils.DivRoundUp(BitUtils.DivRoundUp(h, GobHeight), mipGobBlocksInY);
@@ -88,7 +100,8 @@ namespace Ryujinx.Graphics.Texture
                 depth,
                 blockHeight,
                 gobBlocksInY,
-                gobBlocksInZ);
+                gobBlocksInZ,
+                gobBlocksInTileX);
 
             if (!is3D)
             {
@@ -124,27 +137,37 @@ namespace Ryujinx.Graphics.Texture
             int depth,
             int blockHeight,
             int gobBlocksInY,
-            int gobBlocksInZ)
+            int gobBlocksInZ,
+            int gobBlocksInTileX)
         {
-            height = BitUtils.DivRoundUp(height, blockHeight);
-
-            while (height <= (gobBlocksInY >> 1) * GobHeight && gobBlocksInY != 1)
+            if (gobBlocksInTileX < 2)
             {
-                gobBlocksInY >>= 1;
-            }
+                height = BitUtils.DivRoundUp(height, blockHeight);
 
-            while (depth <= (gobBlocksInZ >> 1) && gobBlocksInZ != 1)
-            {
-                gobBlocksInZ >>= 1;
-            }
+                while (height <= (gobBlocksInY >> 1) * GobHeight && gobBlocksInY != 1)
+                {
+                    gobBlocksInY >>= 1;
+                }
 
-            int blockOfGobsSize = gobBlocksInY * gobBlocksInZ * GobSize;
+                while (depth <= (gobBlocksInZ >> 1) && gobBlocksInZ != 1)
+                {
+                    gobBlocksInZ >>= 1;
+                }
 
-            int sizeInBlockOfGobs = size / blockOfGobsSize;
+                int blockOfGobsSize = gobBlocksInY * gobBlocksInZ * GobSize;
 
-            if (size != sizeInBlockOfGobs * blockOfGobsSize)
+                int sizeInBlockOfGobs = size / blockOfGobsSize;
+
+                if (size != sizeInBlockOfGobs * blockOfGobsSize)
+                {
+                    size = (sizeInBlockOfGobs + 1) * blockOfGobsSize;
+                }
+            }
+            else
             {
-                size = (sizeInBlockOfGobs + 1) * blockOfGobsSize;
+                int alignment = (gobBlocksInTileX * GobSize) * gobBlocksInY * gobBlocksInZ;
+
+                size = BitUtils.AlignUp(size, alignment);
             }
 
             return size;
@@ -164,12 +187,22 @@ namespace Ryujinx.Graphics.Texture
             width  = BitUtils.DivRoundUp(width,  blockWidth);
             height = BitUtils.DivRoundUp(height, blockHeight);
 
-            int gobWidth = gobBlocksInTileX * (GobStride / bytesPerPixel);
+            int gobWidth  = (GobStride / bytesPerPixel) * gobBlocksInTileX;
+            int gobHeight = gobBlocksInY * GobHeight;
+
+            int alignment = gobWidth;
+
+            if (depth < gobBlocksInZ || width <= gobWidth || height <= gobHeight)
+            {
+                alignment = GobStride / bytesPerPixel;
+            }
+
+            (gobBlocksInY, gobBlocksInZ) = GetMipGobBlockSizes(height, depth, blockHeight, gobBlocksInY, gobBlocksInZ);
 
             int blockOfGobsHeight = gobBlocksInY * GobHeight;
             int blockOfGobsDepth  = gobBlocksInZ;
 
-            width  = BitUtils.AlignUp(width,  gobWidth);
+            width  = BitUtils.AlignUp(width,  alignment);
             height = BitUtils.AlignUp(height, blockOfGobsHeight);
             depth  = BitUtils.AlignUp(depth,  blockOfGobsDepth);