From b530f0e1104723b894695b2860cf0f568f24cc9a Mon Sep 17 00:00:00 2001 From: riperiperi Date: Tue, 2 Mar 2021 22:30:54 +0000 Subject: Texture Cache: "Texture Groups" and "Texture Dependencies" (#2001) * Initial implementation (3d tex mips broken) This works rather well for most games, just need to fix 3d texture mips. * Cleanup * Address feedback * Copy Dependencies and various other fixes * Fix layer/level offset for copy from view<->view. * Remove dirty flag from dependency The dirty flag behaviour is not needed - DeferredCopy is all we need. * Fix tracking mip slices. * Propagate granularity (fix astral chain) * Address Feedback pt 1 * Save slice sizes as part of SizeInfo * Fix nits * Fix disposing multiple dependencies causing a crash This list is obviously modified when removing dependencies, so create a copy of it. --- Ryujinx.Graphics.Texture/SizeCalculator.cs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'Ryujinx.Graphics.Texture/SizeCalculator.cs') diff --git a/Ryujinx.Graphics.Texture/SizeCalculator.cs b/Ryujinx.Graphics.Texture/SizeCalculator.cs index 2dc60869..7eee13c0 100644 --- a/Ryujinx.Graphics.Texture/SizeCalculator.cs +++ b/Ryujinx.Graphics.Texture/SizeCalculator.cs @@ -9,6 +9,19 @@ namespace Ryujinx.Graphics.Texture { private const int StrideAlignment = 32; + private static int Calculate3DOffsetCount(int levels, int depth) + { + int offsetCount = depth; + + while (--levels > 0) + { + depth = Math.Max(1, depth >> 1); + offsetCount += depth; + } + + return offsetCount; + } + public static SizeInfo GetBlockLinearTextureSize( int width, int height, @@ -27,8 +40,9 @@ namespace Ryujinx.Graphics.Texture int layerSize = 0; - int[] allOffsets = new int[levels * layers * depth]; + int[] allOffsets = new int[is3D ? Calculate3DOffsetCount(levels, depth) : levels * layers * depth]; int[] mipOffsets = new int[levels]; + int[] sliceSizes = new int[levels]; int mipGobBlocksInY = gobBlocksInY; int mipGobBlocksInZ = gobBlocksInZ; @@ -36,6 +50,8 @@ namespace Ryujinx.Graphics.Texture int gobWidth = (GobStride / bytesPerPixel) * gobBlocksInTileX; int gobHeight = gobBlocksInY * GobHeight; + int depthLevelOffset = 0; + for (int level = 0; level < levels; level++) { int w = Math.Max(1, width >> level); @@ -86,13 +102,16 @@ namespace Ryujinx.Graphics.Texture int zLow = z & mask; int zHigh = z & ~mask; - allOffsets[z * levels + level] = baseOffset + zLow * gobSize + zHigh * sliceSize; + allOffsets[z + depthLevelOffset] = baseOffset + zLow * gobSize + zHigh * sliceSize; } } mipOffsets[level] = layerSize; + sliceSizes[level] = totalBlocksOfGobsInY * robSize; + + layerSize += totalBlocksOfGobsInZ * sliceSizes[level]; - layerSize += totalBlocksOfGobsInZ * totalBlocksOfGobsInY * robSize; + depthLevelOffset += d; } if (layers > 1) @@ -133,7 +152,7 @@ namespace Ryujinx.Graphics.Texture } } - return new SizeInfo(mipOffsets, allOffsets, levels, layerSize, totalSize); + return new SizeInfo(mipOffsets, allOffsets, sliceSizes, depth, levels, layerSize, totalSize, is3D); } public static SizeInfo GetLinearTextureSize(int stride, int height, int blockHeight) @@ -142,7 +161,7 @@ namespace Ryujinx.Graphics.Texture // so we only need to handle a single case (2D textures without mipmaps). int totalSize = stride * BitUtils.DivRoundUp(height, blockHeight); - return new SizeInfo(new int[] { 0 }, new int[] { 0 }, 1, totalSize, totalSize); + return new SizeInfo(totalSize); } private static int AlignLayerSize( -- cgit v1.2.3