diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs index 85ad0bb0..9a8d048e 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs @@ -541,7 +541,8 @@ namespace Ryujinx.Graphics.Gpu.Image depth, lhs.FormatInfo.BlockHeight, lhs.GobBlocksInY, - lhs.GobBlocksInZ); + lhs.GobBlocksInZ, + level); return gobBlocksInY == rhs.GobBlocksInY && gobBlocksInZ == rhs.GobBlocksInZ; @@ -587,7 +588,8 @@ namespace Ryujinx.Graphics.Gpu.Image lhsDepth, lhs.FormatInfo.BlockHeight, lhs.GobBlocksInY, - lhs.GobBlocksInZ); + lhs.GobBlocksInZ, + lhsLevel); int rhsHeight = Math.Max(1, rhs.Height >> rhsLevel); int rhsDepth = Math.Max(1, rhs.GetDepth() >> rhsLevel); @@ -597,7 +599,8 @@ namespace Ryujinx.Graphics.Gpu.Image rhsDepth, rhs.FormatInfo.BlockHeight, rhs.GobBlocksInY, - rhs.GobBlocksInZ); + rhs.GobBlocksInZ, + rhsLevel); return lhsGobBlocksInY == rhsGobBlocksInY && lhsGobBlocksInZ == rhsGobBlocksInZ; diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index dbcb2e75..bade9bbb 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs @@ -484,7 +484,7 @@ namespace Ryujinx.Graphics.Gpu.Image depthOrLayers = Math.Max(1, depthOrLayers >> minLod); } - (gobBlocksInY, gobBlocksInZ) = SizeCalculator.GetMipGobBlockSizes(height, depth, formatInfo.BlockHeight, gobBlocksInY, gobBlocksInZ); + (gobBlocksInY, gobBlocksInZ) = SizeCalculator.GetMipGobBlockSizes(height, depth, formatInfo.BlockHeight, gobBlocksInY, gobBlocksInZ, minLod); } levels = (maxLod - minLod) + 1; diff --git a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs index 09eaf300..503985c9 100644 --- a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs +++ b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs @@ -143,7 +143,7 @@ namespace Ryujinx.Graphics.Texture mipGobBlocksInY >>= 1; } - while (d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1) + if (level > 0 && d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1) { mipGobBlocksInZ >>= 1; } @@ -407,7 +407,7 @@ namespace Ryujinx.Graphics.Texture mipGobBlocksInY >>= 1; } - while (d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1) + if (level > 0 && d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1) { mipGobBlocksInZ >>= 1; } diff --git a/src/Ryujinx.Graphics.Texture/SizeCalculator.cs b/src/Ryujinx.Graphics.Texture/SizeCalculator.cs index 5568784f..4ddd8d4d 100644 --- a/src/Ryujinx.Graphics.Texture/SizeCalculator.cs +++ b/src/Ryujinx.Graphics.Texture/SizeCalculator.cs @@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Texture int gobBlocksInTileX, int gpuLayerSize = 0) { - bool is3D = depth > 1; + bool is3D = depth > 1 || gobBlocksInZ > 1; int layerSize = 0; @@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Texture mipGobBlocksInY >>= 1; } - while (d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1) + if (level > 0 && d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1) { mipGobBlocksInZ >>= 1; } @@ -88,6 +88,9 @@ namespace Ryujinx.Graphics.Texture int robSize = widthInGobs * mipGobBlocksInY * mipGobBlocksInZ * GobSize; + mipOffsets[level] = layerSize; + sliceSizes[level] = totalBlocksOfGobsInY * robSize; + if (is3D) { int gobSize = mipGobBlocksInY * GobSize; @@ -105,10 +108,18 @@ namespace Ryujinx.Graphics.Texture allOffsets[z + depthLevelOffset] = baseOffset + zLow * gobSize + zHigh * sliceSize; } + + int gobRemainderZ = d % mipGobBlocksInZ; + + if (gobRemainderZ != 0 && level == levels - 1) + { + // The slice only covers up to the end of this slice's depth, rather than the full aligned size. + // Avoids size being too large on partial views of 3d textures. + + sliceSizes[level] -= gobSize * (mipGobBlocksInZ - gobRemainderZ); + } } - mipOffsets[level] = layerSize; - sliceSizes[level] = totalBlocksOfGobsInY * robSize; levelSizes[level] = totalBlocksOfGobsInZ * sliceSizes[level]; layerSize += levelSizes[level]; @@ -267,7 +278,8 @@ namespace Ryujinx.Graphics.Texture int depth, int blockHeight, int gobBlocksInY, - int gobBlocksInZ) + int gobBlocksInZ, + int level = int.MaxValue) { height = BitUtils.DivRoundUp(height, blockHeight); @@ -276,7 +288,7 @@ namespace Ryujinx.Graphics.Texture gobBlocksInY >>= 1; } - while (depth <= (gobBlocksInZ >> 1) && gobBlocksInZ != 1) + while (level-- > 0 && depth <= (gobBlocksInZ >> 1) && gobBlocksInZ != 1) { gobBlocksInZ >>= 1; }