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.
This commit is contained in:
riperiperi 2021-03-02 22:30:54 +00:00 committed by GitHub
parent 7a90abc035
commit b530f0e110
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1915 additions and 220 deletions

View file

@ -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 * totalBlocksOfGobsInY * robSize;
layerSize += totalBlocksOfGobsInZ * sliceSizes[level];
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(